Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
ben999B

ben999

@ben999
About
Posts
163
Topics
18
Shares
0
Groups
0
Followers
1
Following
0

Posts

Recent Best Controversial

  • Automatic LED light - high WAF inside :)
    ben999B ben999

    Hi guys

    A new project came on top of the others : ceiling light

    The wife kinda likes the idea behind MySensors and openHab, as home automation and security system
    But i had to hit hard to get it fully accepted. So here comes the "cat shaped ceiling light" !!!

    (0_1508911480537_IMG_6161[1].JPG
    (Ok I know, ceiling is not finished yet... it has to be spotless as this kind of light reveals everything...)
    LED strip is glued on the edge of the board, powered via a 12V power supply which is controlled via an OMRON SSR relay

    Some AutoCad and CNC later... :

    0_1508914575098_IMG_6156.JPG

    0_1508914588720_IMG_6157.JPG

    This is highly inspired by Aproxx's work
    https://www.openhardware.io/view/77/AC-DC-double-solid-state-relay-module

    What I want it to do :

    • switch on the light when motion (PIR sensor)
    • switch itself off with delay (PIR kind enough to do that as well)
    • measure room light level so as to switch light on only when needed
    • have 3 modes controlled via openHab : fully automatic, always ON, always OFF

    So far i have managed to create a 3-state selector in openhab with this:

    • ".items" file: String HouseMode "House Mode [%s]"
    • ".sitemap" file: Switch item=LightMode mappings=[ON=1, AUTO=2, OFF=1]

    0_1508920812417_IMG_6164.PNG

    Now I am having some trouble with the sketch...
    I guess I should be using S_CUSTOM and V_CUSTOM (instead of S_BINARY and V_STATUS) as the "LightMode" variable can take up to 3 states...
    How do i then retreive that value?

    void receive(const MyMessage &message)
    int lightMode = message.getInt();
    

    Thanks for your input and comments :)

    My Project

  • Alarm Clock
    ben999B ben999

    Hi !
    I am having a go myself at the alarm clock project !!
    Nokia 5110 screen
    Rotary encoder
    No RTC :)
    LiIon18650 cell

    So far, I managed to get time from controller via requestTime()
    Then display it on node screen

    Now i would like the node to send a message to the controller : goal is to check in PaperUI the alarm time that has been set on the clock
    Later on i would like to be able to set/unset alarm from PaperUI
    And even later on i would like to be able to set alarm from PaperUI as well as from alarm clock

    Thanks a lot for your input and comments
    I am having so much fun with my sensors !!!

    0_1498933565366_FullSizeRender.jpg

    My Project

  • NRF24 Range
    ben999B ben999

    Dusting an old post here :)

    That previous video brings a solution... but it seems that it is not quite the right way to do it (by reading the comments, looks like keeping the original trace and adding a wire is not the recommended fashion..)

    Here is another approach, that looks good!
    http://www.instructables.com/id/Enhanced-NRF24L01/

    What about power consumption ? Does it necessarily go up as the range increases ?

    General Discussion

  • Alarm Clock
    ben999B ben999

    And here is my code up-to now :

    What it does on node's side

    • displays time, date, and alarm if set (if not, displays "alarm Off")
    • updates itself once a week by asking controller
    • list menus to :
      • set alarm on or off
      • set alarm time (hour and minute)
      • change screen contrast

    What is does on openHab

    • turns on and off alarm via a switch (item #1 - lock sensor)

    • displays time of alarm and when it has been updated (item #0 - text)

    I have ordered a WTV020-SD-16P module so that my little guys can wake-up to the sound of "the Final Countdown" !
    http://www.ebay.com/itm/U-disk-audio-player-TF-SD-card-voice-module-MP3-Sound-WTV020-SD-16P-Arduino/310629013078?ssPageName=STRK%3AMEBIDX%3AIT&_trksid=p2057872.m2749.l2649

    And last on the list, being able to change alarm time via paperUI and iPhone app

    Thanks for your comments (be gentle on arduino sketch ;) )

    /*******Interrupt-based Rotary Encoder Sketch*******
    by Simon Merrett, based on insight from Oleg Mazurov, Nick Gammon, rt, Steve Spence */
    
    //#define MY_DEBUG          // Enable debug prints
    #define MY_RADIO_NRF24   // Enable and select radio type attached
    
    #define MY_PARENT_ID 0
    #define MY_NODE_ID 50
    
    #include <SPI.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_PCD8544.h>
    #include <MySensors.h>
    #include <Time.h>
    
    #define ALARM_ID 0                      // Id of TimeOfAlarm value
    #define ACTIV_ID 1                      // Id of ActivateAlarm switch
    
    static int pinA = 2; // Our first hardware interrupt pin is digital pin 2
    static int pinB = 3; // Our second hardware interrupt pin is digital pin 3
    static int enSW = 4; // Rotary switch push-button
    
    volatile byte aFlag = 0; // let's us know when we're expecting a rising edge on pinA to signal that the encoder has arrived at a detent
    volatile byte bFlag = 0; // let's us know when we're expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set)
    volatile uint16_t encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255
    volatile uint16_t oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor)
    volatile byte reading = 0; //somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent
    
    // Software SPI (slower updates, more flexible pin options):
    // pin 7 - Serial clock out (SCLK)
    // pin 6 - Serial data out (DIN)
    // pin 5 - Data/Command select (D/C)
    // pin 4 - LCD chip select (CS)
    // pin 8 - LCD reset (RST)
    Adafruit_PCD8544 display = Adafruit_PCD8544(A4, A3, A2, A1, A0);
    
    //Declare the Menus you need.
    char menu[][10] = {"Activer", "Regler", "Ecran", "Volume", "Retour"};
    byte itemCount = 4;
    int itemSelected;
    byte runOnceAWeek = 1;   //allow for time update once a week
    
    char dataBuffer[20];  // for sprintf function
    bool alarmStatus;     // Alarm set/unset status
    int alarmHour = 0;
    int alarmMin = 0;
    int contrast = 50;
    int backlightFlag = 0;
    int backlightCountdown = 10000;   // switch off backlight after XX millisec
    int loopTime = 0;
    int prevMillis = 0;
    
    MyMessage  textMsg(ALARM_ID, V_TEXT);      // Initialize clock messages
    MyMessage alarmMsg(ACTIV_ID, V_LOCK_STATUS);    // Initialize switch messages
    
    void presentation()  {
      sendSketchInfo("Loulou's Clock", "08.07.2017");
      present(ALARM_ID, S_INFO);
      present(ACTIV_ID, S_LOCK);
    }
    
    void setup() {
      pinMode(A5, OUTPUT);     //5110 screen backlight
      digitalWrite(A5, LOW);
      display.begin();
      pinMode(enSW, INPUT_PULLUP);
      pinMode(pinA, INPUT_PULLUP);
      pinMode(pinB, INPUT_PULLUP);
      attachInterrupt(0, PinA, RISING);
      attachInterrupt(1, PinB, RISING);
      Serial.begin(115200);
      display.setContrast(contrast);
      display.display();
      display.clearDisplay();
      display.setTextColor(BLACK);
    
      int clockCounter = 0;
      while (timeStatus() == timeNotSet && clockCounter < 60) {
        requestTime();
        clockCounter++;
        wait(1000);
        /*
          Serial.print("état reception:");
          Serial.println(timeStatus());
        */
        if (clockCounter > 16) {
          /*
            Serial.print(F("**Failed Clock**"));
            Serial.print(F("*Syncronization*"));
          */
          break;
        }
      }
      alarmStatus = loadState(0);    // Read last lock status from eeprom
      setAlarmState(alarmStatus, true); // Now set the last known state and send it to controller
      sendTime();
    }
    
    void loop() {
      /*** synchronise clock node with controller from time to time... ***/
      if (weekday() == 5 && runOnceAWeek == 1) {
        requestTime();
        runOnceAWeek = 0;
      }
      if (weekday() != 5)
        runOnceAWeek = 1;
    
      /*** switch off backlight function ***/
      loopTime = millis() - prevMillis;
      prevMillis = millis();
      backlightFlag = backlightFlag + loopTime;
      if (backlightFlag > backlightCountdown) {
        digitalWrite(A5, HIGH);
        backlightFlag = backlightCountdown + 1;   // to avoid overflow
      }
      else
        digitalWrite(A5, LOW);
    
      /*** Show time on the default Screen ***/
      display.clearDisplay();
      display.setTextSize(2);
      display.setCursor(14, 2);
      sprintf(dataBuffer, "%02u:%02u ", hour() + 2, minute());
      display.print(dataBuffer);
      display.display();
      display.setTextSize(1);
      display.setCursor(14, 22);
      sprintf(dataBuffer, "%02u-%02u-%04u ", day(), month(), year());
      display.print(dataBuffer);
      display.display();
    
      if (alarmStatus == 0) {       //Show whether alarm is on or off
        display.setCursor(14, 35);
        sprintf(dataBuffer, "Alarme OFF");
      }
      else {
        display.setCursor(7, 35);
        char alarmText[7] = "Alarme";
        sprintf(dataBuffer, "%s %02u:%02u", alarmText, alarmHour, alarmMin);
      }
      display.print(dataBuffer);
      display.setTextSize(1);
      display.display();
    
      /*** Enter the settings menu if select Switch is pressed ***/
      if (digitalRead(enSW) == 0) {
        while (digitalRead(enSW) == 0); //wait till switch is released.
        encoderPos = 0;
        digitalWrite(A5, LOW);          // switch backlight ON when entering menu
        switch (encoderPos) {           //Enter main program
          case 0: display.clearDisplay();
            display.setTextSize(2);
            display.setCursor(0, 10);
            display.println(menu[encoderPos]);
            display.display();
            while (digitalRead(enSW)) {
              encoderPos = constrain(encoderPos, 0, itemCount);
              display.clearDisplay();
              display.setCursor(0, 0);
              display.println(menu[encoderPos]);
              if (encoderPos < 0)
                encoderPos = itemCount;
              if  (encoderPos > itemCount)
                encoderPos = 0;
              display.display();
            }
            while (digitalRead(enSW) == 0);
            itemSelected = encoderPos;
          default: break;
        }
        switch (itemSelected) {
          case 0: display.clearDisplay();      //ACTIVATE ALARME
            display.setTextSize(2);
            display.setCursor(0, 10);
            display.println(menu[itemSelected]);
            display.display();
            encoderPos = alarmStatus;
            while (digitalRead(enSW)) {
              encoderPos = constrain(encoderPos, 0, 1);
              display.clearDisplay();
              display.setCursor(0, 0);
              display.print(menu[itemSelected]);
              display.setCursor(16, 26);
              display.print(encoderPos);
              if (encoderPos == 0)  {
                sprintf(dataBuffer, "OFF");
              }
              else  {
                sprintf(dataBuffer, "ON");
              }
              display.setCursor(45, 26);
              display.print(dataBuffer);
              display.display();
            }
            if (encoderPos != alarmStatus)  {
              alarmStatus = encoderPos;
              send(alarmMsg.set(alarmStatus));
            }
            while (digitalRead(enSW) == 0);
            break;
    
          case 1: display.clearDisplay();     //SET ALARME TIME
            display.setTextSize(2);
            display.setCursor(0, 10);
            display.print(menu[itemSelected]);
            display.display();
            encoderPos = alarmHour;
            while (digitalRead(enSW)) {       //SET ALARME HOUR
              encoderPos = constrain(encoderPos, 00, 23);
              display.clearDisplay();
              display.setCursor(0, 0);
              display.print(menu[itemSelected]);
              display.setCursor(10, 26);       //HOUR LOCATION
              display.print(encoderPos);
              if (encoderPos < 0)
                encoderPos = 23;
              if  (encoderPos > 23)
                encoderPos = 0;
              display.setCursor(35, 26);       // ":" LOCATION
              display.print(":");
              display.setCursor(50, 26);       //MINUTE LOCATION
              display.print(alarmMin);
              display.display();
            }
            if (encoderPos != alarmHour)  {
              alarmHour = encoderPos;
              sendTime();
            }
            encoderPos = alarmMin;
            while (digitalRead(enSW)) {        //SET ALARME MINUTE
              encoderPos = constrain(encoderPos, 00, 59);
              display.clearDisplay();
              display.setCursor(0, 0);
              display.print(menu[itemSelected]);
              display.setCursor(10, 26);       //HOUR LOCATION
              display.print(alarmHour);
              display.setCursor(35, 26);       //":" LOCATION
              display.print(":");
              display.setCursor(50, 26);       //MINUTE LOCATION
              display.print(encoderPos);
              if (encoderPos < 0)
                encoderPos = 59;
              if  (encoderPos > 59)
                encoderPos = 0;
              display.display();
            }
            if (encoderPos != alarmMin)  {
              alarmMin = encoderPos;
              sendTime();
            }
            while (digitalRead(enSW) == 0);
            break;
    
          case 2: display.clearDisplay();        //CONTRAST
            display.setTextSize(2);
            display.setCursor(0, 10);
            display.print(menu[itemSelected]);
            display.display();
            encoderPos = contrast;
            while (digitalRead(enSW)) {
              encoderPos = constrain(encoderPos, 0, 100);
              display.clearDisplay();
              display.setCursor(0, 0);
              display.print(menu[itemSelected]);
              display.setCursor(16, 16);
              display.print(encoderPos);
              if (encoderPos < 0)
                encoderPos = 100;
              if  (encoderPos > 100)
                encoderPos = 0;
              display.setContrast(encoderPos);
              display.display();
            }
            if (encoderPos != contrast)
              contrast = encoderPos;
            while (digitalRead(enSW) == 0);
            break;
          default: break;
        }
      }
    }
    
    
    /*** send alarm time to controller ****/
    void sendTime()  {
      sprintf(dataBuffer, "%02u:%02u ", alarmHour, alarmMin);
      send(textMsg.set(dataBuffer));
      wait(1000);
    }
    
    /*** Activate alarm ***/
    void setAlarmState(bool state, bool doSend) {
      if (doSend)
        send(alarmMsg.set(state));
      saveState(0, state);
      alarmStatus = state;
    }
    
    /*** receive alarme state from controller ***/
    void receive(const MyMessage & message) {
      if (message.type == V_LOCK_STATUS) {
        setAlarmState(message.getBool(), false);      // Change relay state
      }
    }
    
    /*** receive a new time value ***/
    void receiveTime(unsigned long controllerTime) {
      setTime(controllerTime);
    }
    
    /*** rotary encoder interrupt function ***/
    void PinA() {
      cli(); //stop interrupts happening before we read pin values
      reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values
      if (reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
        encoderPos --; //decrement the encoder's position count
        bFlag = 0; //reset flags for the next turn
        aFlag = 0; //reset flags for the next turn
        backlightFlag = 0;
      }
      else if (reading == B00000100) bFlag = 1; //signal that we're expecting pinB to signal the transition to detent from free rotation
      sei(); //restart interrupts
    }
    
    
    void PinB() {
      cli(); //stop interrupts happening before we read pin values
      reading = PIND & 0xC; //read all eight pin values then strip away all but pinA and pinB's values
      if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
        encoderPos ++; //increment the encoder's position count
        bFlag = 0; //reset flags for the next turn
        aFlag = 0; //reset flags for the next turn
        backlightFlag = 0;
      }
      else if (reading == B00001000) aFlag = 1; //signal that we're expecting pinA to signal the transition to detent from free rotation
      sei(); //restart interrupts
    }```
    My Project

  • CNC PCB milling
    ben999B ben999

    @neverdie just a thought
    One is able to customise a program header and footer of GCode programs
    Maybe you could use a “coolant off” and “coolant on” (M07, M08 and M09 if I remember correctly) to achieve your goal?

    General Discussion

  • Alarm Clock
    ben999B ben999

    Full sketch
    Some mods to come:

    • stop alarm while ringing
    • snoze
    //#define MY_DEBUG          // Enable debug prints
    #define MY_RADIO_NRF24   // Enable and select radio type attached
    
    #define MY_PARENT_ID 0
    #define MY_NODE_ID 50
    
    #include <SPI.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_PCD8544.h>
    #include <MySensors.h>
    #include <Time.h>
    #include <Wtv020sd16p.h>
    
    #define ALARM_ID 0                      // Id of TimeOfAlarm value
    #define ACTIV_ID 1                      // Id of ActivateAlarm switch
    
    int resetPin = 5;  // The pin number of the reset pin.
    int clockPin = 6;  // The pin number of the clock pin.
    int dataPin = 7;  // The pin number of the data pin.
    int busyPin = 8;  // The pin number of the busy pin.
    
    static int pinA = 2; // Our first hardware interrupt pin is digital pin 2
    static int pinB = 3; // Our second hardware interrupt pin is digital pin 3
    static int enSW = 4; // Rotary switch push-button
    
    volatile byte aFlag = 0; // let's us know when we're expecting a rising edge on pinA to signal that the encoder has arrived at a detent
    volatile byte bFlag = 0; // let's us know when we're expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set)
    volatile uint16_t encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255
    volatile uint16_t oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor)
    volatile byte reading = 0; //somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent
    
    // Software SPI (slower updates, more flexible pin options):
    // pin 7 - Serial clock out (SCLK)
    // pin 6 - Serial data out (DIN)
    // pin 5 - Data/Command select (D/C)
    // pin 4 - LCD chip select (CS)
    // pin 8 - LCD reset (RST)
    Adafruit_PCD8544 display = Adafruit_PCD8544(A4, A3, A2, A1, A0);
    
    
    // Create an instance of the Wtv020sd16p class.
    // 1st parameter: Reset pin number.
    // 2nd parameter: Clock pin number.
    // 3rd parameter: Data pin number.
    // 4th parameter: Busy pin number.
    Wtv020sd16p wtv020sd16p(resetPin, clockPin, dataPin, busyPin);
    
    //Declare the Menus you need.
    char menu[][20] = {"ActiverAlarme", "Regler Alarme" , "Contra-ste", "Volume",
                       "MusiqueAlarme", "EcouterMusique", "Retour"
                      };
    byte itemCount = 6;
    int itemSelected;
    byte runOnceAWeek = 1;   //allow for time update once a week
    
    char dataBuffer[20];  // for sprintf function
    bool alarmStatus;     // Alarm set/unset status
    int alarmHour = 0;
    int alarmMin = 0;
    int alarmTune = 1;
    unsigned int alarmVolume = 5;
    int contrast = 50;
    int backlightFlag = 0;
    int backlightCountdown = 10000;   // switch off backlight after XX millisec
    int loopTime = 0;
    int prevMillis = 0;
    byte smallFont = 1;
    byte bigFont = 2;
    
    MyMessage  textMsg(ALARM_ID, V_TEXT);      // Initialize clock messages
    MyMessage alarmMsg(ACTIV_ID, V_LOCK_STATUS);    // Initialize switch messages
    
    void presentation()  {
      sendSketchInfo("Loulou's Clock", "25.07.2017");
      present(ALARM_ID, S_INFO);
      present(ACTIV_ID, S_LOCK);
    }
    
    void setup() {
      wtv020sd16p.reset();     //MP3 player
      delay(1000);
      wtv020sd16p.setVolume(alarmVolume);
      pinMode(A5, OUTPUT);     //5110 screen backlight
      digitalWrite(A5, LOW);
      display.begin();
      pinMode(enSW, INPUT_PULLUP);
      pinMode(pinA, INPUT_PULLUP);
      pinMode(pinB, INPUT_PULLUP);
      attachInterrupt(0, PinA, RISING);
      attachInterrupt(1, PinB, RISING);
      Serial.begin(115200);
      display.setContrast(contrast);
      display.display();
      display.clearDisplay();
      display.setTextColor(BLACK);
    
      int clockCounter = 0;
      while (timeStatus() == timeNotSet && clockCounter < 60) {
        requestTime();
        clockCounter++;
        wait(1000);
        /*
          Serial.print("état reception:");
          Serial.println(timeStatus());
        */
        if (clockCounter > 16) {
          /*
            Serial.print(F("**Failed Clock**"));
            Serial.print(F("*Syncronization*"));
          */
          break;
        }
      }
      alarmStatus = loadState(0);    // Read last lock status from eeprom
      setAlarmState(alarmStatus, true); // Now set the last known state and send it to controller
      sendTime();
    }
    
    void loop() {
      /*** ALARM !!! ***/
      while (hour() + 2 == alarmHour && minute() == alarmMin) {
        digitalWrite(A5, LOW);          // switch backlight ON when entering menu
        display.clearDisplay();
        display.setTextSize(1);
        display.setCursor(2, 2);
        display.print("Debout Axou");
        display.display();
        display.setCursor(2, 20);
        display.print("Faut y aller");
        display.display();
        display.setCursor(2, 40);
        sprintf(dataBuffer, "Il est %02u:%02u ", hour() + 2, minute());
        display.print(dataBuffer);
        display.display();
        wtv020sd16p.playVoice(alarmTune - 1);
      }
    
      /*** synchronise clock node with controller from time to time... ***/
      if (weekday() == 5 && runOnceAWeek == 1) {
        requestTime();
        runOnceAWeek = 0;
      }
      if (weekday() != 5)
        runOnceAWeek = 1;
    
      /*** switch off backlight function ***/
      loopTime = millis() - prevMillis;
      prevMillis = millis();
      backlightFlag = backlightFlag + loopTime;
      if (backlightFlag > backlightCountdown) {
        digitalWrite(A5, HIGH);
        backlightFlag = backlightCountdown + 1;   // to avoid overflow
      }
      else
        digitalWrite(A5, LOW);
    
      /*** Show time on the default Screen ***/
      display.clearDisplay();
      display.setTextSize(2);
      display.setCursor(14, 2);
      sprintf(dataBuffer, "%02u:%02u ", hour() + 2, minute());
      display.print(dataBuffer);
      //display.display();
      display.setTextSize(1);
      display.setCursor(14, 22);
      sprintf(dataBuffer, "%02u-%02u-%04u ", day(), month(), year());
      display.print(dataBuffer);
      display.display();
    
      if (alarmStatus == 0) {       //Show whether alarm is on or off
        display.setCursor(14, 35);
        sprintf(dataBuffer, "Alarme OFF");
      }
      else {
        display.setCursor(7, 35);
        char alarmText[7] = "Alarme";
        sprintf(dataBuffer, "%s %02u:%02u", alarmText, alarmHour, alarmMin);
      }
      display.print(dataBuffer);
      display.display();
    
      /*** Enter the settings menu if select Switch is pressed ***/
      if (digitalRead(enSW) == 0) {
        while (digitalRead(enSW) == 0); //wait till switch is released.
        encoderPos = 0;
        digitalWrite(A5, LOW);          // switch backlight ON when entering menu
        switch (encoderPos) {           //Enter main program
          case 0: display.clearDisplay();
            display.setTextSize(2);
            display.setCursor(0, 10);
            display.println(menu[encoderPos]);
            display.display();
            while (digitalRead(enSW)) {
              encoderPos = constrain(encoderPos, 0, itemCount);
              display.clearDisplay();
              display.setCursor(0, 0);
              display.println(menu[encoderPos]);
              if (encoderPos < 0)
                encoderPos = itemCount;
              if  (encoderPos > itemCount)
                encoderPos = 0;
              display.display();
            }
            while (digitalRead(enSW) == 0);
            itemSelected = encoderPos;
          default: break;
        }
        switch (itemSelected) {
          case 0: display.clearDisplay();      //ACTIVATE ALARME
            display.setTextSize(bigFont);
            display.setCursor(0, 10);
            display.println(menu[itemSelected]);
            display.display();
            encoderPos = alarmStatus;
            while (digitalRead(enSW)) {
              encoderPos = constrain(encoderPos, 0, 1);
              display.clearDisplay();
              display.setCursor(0, 0);
              display.print(menu[itemSelected]);
              display.setCursor(16, 34);
              display.print(encoderPos);
              if (encoderPos == 0)  {
                sprintf(dataBuffer, "OFF");
              }
              else  {
                sprintf(dataBuffer, "ON");
              }
              display.setCursor(45, 34);
              display.print(dataBuffer);
              display.display();
            }
            if (encoderPos != alarmStatus)  {
              alarmStatus = encoderPos;
              send(alarmMsg.set(alarmStatus));
            }
            while (digitalRead(enSW) == 0);
            break;
    
          case 1: display.clearDisplay();     //SET ALARME TIME
            display.setTextSize(bigFont);
            display.setCursor(0, 10);
            display.print(menu[itemSelected]);
            display.display();
            encoderPos = alarmHour;
            while (digitalRead(enSW)) {       //SET ALARME HOUR
              encoderPos = constrain(encoderPos, 00, 23);
              display.clearDisplay();
              display.setCursor(0, 0);
              display.print(menu[itemSelected]);
              display.setCursor(10, 34);       //HOUR LOCATION
              display.print(encoderPos);
              if (encoderPos < 0)
                encoderPos = 23;
              if  (encoderPos > 23)
                encoderPos = 0;
              display.setCursor(35, 34);       // ":" LOCATION
              display.print(":");
              display.setCursor(50, 34);       //MINUTE LOCATION
              display.print(alarmMin);
              display.display();
            }
            if (encoderPos != alarmHour)  {
              alarmHour = encoderPos;
              sendTime();
            }
            encoderPos = alarmMin;
            while (digitalRead(enSW)) {        //SET ALARME MINUTE
              encoderPos = constrain(encoderPos, 00, 59);
              display.clearDisplay();
              display.setCursor(0, 0);
              display.print(menu[itemSelected]);
              display.setCursor(10, 34);       //HOUR LOCATION
              display.print(alarmHour);
              display.setCursor(35, 34);       //":" LOCATION
              display.print(":");
              display.setCursor(50, 34);       //MINUTE LOCATION
              display.print(encoderPos);
              if (encoderPos < 0)
                encoderPos = 59;
              if  (encoderPos > 59)
                encoderPos = 0;
              display.display();
            }
            if (encoderPos != alarmMin)  {
              alarmMin = encoderPos;
              sendTime();
            }
            while (digitalRead(enSW) == 0);
            break;
    
          case 2: display.clearDisplay();        //CONTRAST
            display.setTextSize(bigFont);
            display.setCursor(0, 10);
            display.print(menu[itemSelected]);
            display.display();
            encoderPos = contrast;
            while (digitalRead(enSW)) {
              encoderPos = constrain(encoderPos, 0, 100);
              display.clearDisplay();
              display.setCursor(0, 0);
              display.print(menu[itemSelected]);
              display.setCursor(16, 16);
              display.print(encoderPos);
              if (encoderPos < 0)
                encoderPos = 100;
              if  (encoderPos > 100)
                encoderPos = 0;
              display.setContrast(encoderPos);
              display.display();
            }
            if (encoderPos != contrast)
              contrast = encoderPos;
            while (digitalRead(enSW) == 0);
            break;
    
          case 3: display.clearDisplay();        //VOLUME
            display.setTextSize(smallFont);
            display.setCursor(0, 10);
            display.print(menu[itemSelected]);
            display.display();
            encoderPos = alarmVolume;
            while (digitalRead(enSW)) {
              encoderPos = constrain(encoderPos, 0, 7);
              display.clearDisplay();
              display.setCursor(0, 0);
              display.print(menu[itemSelected]);
              display.setCursor(16, 34);
              display.print(encoderPos);
              if (encoderPos < 0)
                encoderPos = 7;
              if  (encoderPos > 7)
                encoderPos = 0;
              display.display();
              wtv020sd16p.setVolume(encoderPos);
            }
            alarmVolume = encoderPos;
            while (digitalRead(enSW) == 0);
            break;
    
          case 4: display.clearDisplay();        //ALARM TUNE
            display.setTextSize(bigFont);
            display.setCursor(0, 10);
            display.print(menu[itemSelected]);
            display.display();
            encoderPos = alarmTune;
            while (digitalRead(enSW)) {
              encoderPos = constrain(encoderPos, 1, 10);
              display.clearDisplay();
              display.setCursor(0, 0);
              display.print(menu[itemSelected]);
              display.setCursor(16, 34);
              display.print(encoderPos);
              if (encoderPos < 1)
                encoderPos = 10;
              if  (encoderPos > 10)
                encoderPos = 0;
              display.display();
            }
            alarmTune = encoderPos;
            while (digitalRead(enSW) == 0);
            break;
    
          case 5: display.clearDisplay();        //PLAYER
            display.setTextSize(bigFont);
            display.setCursor(0, 10);
            display.print(menu[itemSelected]);
            display.display();
            encoderPos = 0;
            while (digitalRead(enSW)) {
              encoderPos = constrain(encoderPos, 0, 10);
              display.clearDisplay();
              display.setCursor(0, 0);
              display.print(menu[itemSelected]);
              display.setCursor(16, 34);
              display.print(encoderPos);
              if (encoderPos < 0)
                encoderPos = 10;
              if  (encoderPos > 10)
                encoderPos = 0;
              display.display();
            }
            if (encoderPos == 0)
              wtv020sd16p.stopVoice();
            else
              wtv020sd16p.playVoice(encoderPos - 1);
            while (digitalRead(enSW) == 0);
            break;
    
          default: break;
        }
      }
    }
    
    /*** receive a new time value ***/
    void receiveTime(unsigned long controllerTime) {
      setTime(controllerTime);
    }
    
    /*** send alarm time to controller ****/
    void sendTime()  {
      sprintf(dataBuffer, "%02u:%02u ", alarmHour, alarmMin);
      send(textMsg.set(dataBuffer));
      wait(1000);
    }
    
    /*** Activate alarm ***/
    void setAlarmState(bool state, bool doSend) {
      if (doSend)
        send(alarmMsg.set(state));
      saveState(0, state);
      alarmStatus = state;
    }
    
    /*** receive alarme state from controller ***/
    void receive(const MyMessage & message) {
      if (message.type == V_LOCK_STATUS)
        setAlarmState(message.getBool(), false);
      if (message.type == V_TEXT) {
        char alarmTime[MAX_MESSAGE_LENGTH];
        strncpy(alarmTime, message.data, MAX_MESSAGE_LENGTH);
        char* token = strtok(alarmTime, ":");
        alarmHour = atoi(token);
        token = strtok(NULL, "");
        alarmMin = atoi(token);
      }
    
    }
    
    /*** rotary encoder interrupt function ***/
    void PinA() {
      cli(); //stop interrupts happening before we read pin values
      reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values
      if (reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
        encoderPos --; //decrement the encoder's position count
        bFlag = 0; //reset flags for the next turn
        aFlag = 0; //reset flags for the next turn
        backlightFlag = 0;
      }
      else if (reading == B00000100) bFlag = 1; //signal that we're expecting pinB to signal the transition to detent from free rotation
      sei(); //restart interrupts
    }
    
    
    void PinB() {
      cli(); //stop interrupts happening before we read pin values
      reading = PIND & 0xC; //read all eight pin values then strip away all but pinA and pinB's values
      if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
        encoderPos ++; //increment the encoder's position count
        bFlag = 0; //reset flags for the next turn
        aFlag = 0; //reset flags for the next turn
        backlightFlag = 0;
      }
      else if (reading == B00001000) aFlag = 1; //signal that we're expecting pinA to signal the transition to detent from free rotation
      sei(); //restart interrupts
    }```
    My Project

  • Can't link rfid node item
    ben999B ben999

    @TimO
    Dude, it's awesome :)
    I even get a slider in paperUI to control the lock as well !!!

    BUT... (there's alway's a "but")
    Auto-discovery doesn't work anymore :cry:
    Here is what i get from Karaf when clicking on "refresh" (in Inbox > MySensors Binding > Search )

    21:50:27.220 [DEBUG] [.discovery.MySensorsDiscoveryService] - Stopping MySensors discovery scan
    21:50:27.227 [DEBUG] [.discovery.MySensorsDiscoveryService] - Starting MySensors discovery scan
    

    No more hourglass... no searching...
    Doc, i think we've lost it...

    OpenHAB

  • Servo, dallas and Nano...
    ben999B ben999

    @rejoe2 said in Servo, dallas and Nano...:

    use at least a capacitor as recommended in "Build".

    Forgot to mention that. I do use that capacitor as a standard. Thanks again

    Hardware

  • RPi 3 gateway problem
    ben999B ben999

    Hi @feranto63

    I've had a look at your logs with this tool :
    https://www.mysensors.org/build/parser

    Looks like gateway gets messages from node
    But node doesn't get anything in return

    Do you use "MY_PARENT_NODE_ID" and "MY_NODE_ID" as a config option in your node sketch ?

    Troubleshooting

  • 💬 Building a Raspberry Pi Gateway
    ben999B ben999

    @Yveaux thanks a lot for your answer. Understanding linux is a slow and painful process :laughing:

    Here is the output from your command : dmesg |grep -i tty

    pi@raspberrypi:~ $ dmesg |grep -i tty
    [    0.000000] Kernel command line: 8250.nr_uarts=0 dma.dmachans=0x7f35 bcm2708_fb.fbwidth=656 bcm2708_fb.fbheight=416 bcm2709.boardrev=0xa02082 bcm2709.serial=0xcc3e67e3 smsc95xx.macaddr=B8:27:EB:3E:67:E3 bcm2708_fb.fbswap=1 bcm2709.uart_clock=48000000 vc_mem.mem_base=0x3dc00000 vc_mem.mem_size=0x3f000000  dwc_otg.lpm_enable=0 console=ttyS0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
    [    0.001337] console [tty1] enabled
    [    1.772114] 3f201000.uart: ttyAMA0 at MMIO 0x3f201000 (irq = 87, base_baud = 0) is a PL011 rev2
    

    What a mess...
    ttyAMA0 is the one !!!
    Thanks @Yveaux you got me on the right path !!! Goto next step! :smile:

    Announcements

  • Node battery voltage in openHAB iOS
    ben999B ben999

    Hi all
    I have a question regarding this topic :
    battery powered arduino without resistors
    I have just implemented this in a motion/temp/humidity sensor
    -> Arduino Pro Mini with NRF24, DHT22 and SR501 (converted to 3.3V as per "Build" instruction)
    I inserted this bit of code into mysensor code :

    #include <Vcc.h>
    const float VccExpected   = 3.0;
    const float VccCorrection = 2.860/2.92; 
    Vcc vcc(VccCorrection);
    
    void loop()
    {
        int batteryPcnt = (int)vcc.Read_Perc(VccExpected);
       sendBatteryLevel(batteryPcnt);
    }
    

    I am pretty happy with the result, as i can now see voltage within PaperUI :)

    Now how would i get that in "things", "items" and "sitemap" ? So i can get my node battery voltage in openHAB iOS...
    Do I need to create a new child that "carries" this info?

    Thanks a lot for your help

    OpenHAB

  • Microwave oven (no kidding :D)
    ben999B ben999

    Hi guys,

    My microwave oven broke down last month.

    Not only it's a pain in the backside but it is also more waste for the planet.

    A quick search on the internet educated me about safety and how to test parts.

    Turns out the main board is dead (display works fine, most buttons too but "start" and "stop" buttons are useless).

    New motherboard is difficult to source and is no more available from manufacturer (i bought it 2 years ago but must have been some fairly old design... :face_with_rolling_eyes: )

    So back to drawing board and soldering iron:

    • arduino nano
    • 2.8" TFT colour display
    • rotary encoder
    • salvage "power board" from microwave (gives 12V and 5V)

    I am pretty well on my way design-wise and need a final advice on transistors ; following are 2 arrangements regarding what i would call the "oven door transistor" (the bottom PNP one).
    The 3 NPN transistors at the top drive a relay each one (magnetron, plate and heating resistance). Each transistor is driven by the arduino via a resistor.

    Please accept my apologies if any of my sketches make your eyes bleed. :grin:

    Which one would be the least bad and how could it be improved.

    Thanks a lot for reading :+1:

    EDIT: Sketches drawn with https://www.falstad.com

    1.JPG

    2.JPG

    Hardware

  • 💬 Log Parser
    ben999B ben999

    I have just discovered "The Log Parser" !!!

    WOW that's huge !

    Thumbs up to those involved in that !!! Thanks a lot :)

    Announcements

  • Alarm Clock
    ben999B ben999

    Guys

    Making progress, mainly on sketch-side of it.

    Now on the hardware side of it : i would like to power the clock via a single 18650 cell (2000mah from old laptop)

    So i need a regulation unit, as LiIon cell will run from 4.2V down to 2.3V (cut-off from protection board)

    NRF, arduino nano and 5110 screen need 3.3V supply
    NRF and arduino will draw up to 30mA when transmitting
    5110 screen backlight will draw 50mA, logic seems to draw nearly nothing...
    So that would be a grand total of less than 100mA

    That converter would need to step-down as well as step-up depending on "petrol level" of the cell...
    Does it even exist ??

    @NeverDie suggested this elsewhere on the forum... http://www.ti.com/product/TPS82740B/description&lpos=Middle_Container&lid=Alternative_Devices

    Or shall i simply connect the LiIon cell straight to arduino board (raw pin) and let it power the screen and radio (3.3 pin) ?? As it seems the on-board regulator can handle upto 150mA... smell of burning chips... ? :laughing:

    Would it fit the bill ? Any suggestions ?

    Thanks a lot !

    My Project

  • MySensors - Get Temperature value from another node through the Gateway
    ben999B ben999

    @rejoe2 Dude!!! It worked! Awesome :D Node-to-node is now understood and tested :)

    Now i need (for my personal benefit) to get my node to fetch data from controller
    FHEM seems to be some type of controller software like Openhab and so many others... ? Next move is to discover where and how data is stored within openhab...

    Once again @rejoe2 thank you very much for passing on your knowledge

    Just one remark: Having a display and a sleeping node doesn't fit to well together imo 😀

    I just wanted to make sure you would not lead me to any other way :D as i wanted to understand both ways of sharing data between nodes
    Thank you so much for that :+1:

    Development

  • 💬 Distance Sensor
    ben999B ben999

    I've been fighting with DYP-ME007Y myself for the last few days...
    Originally i wanted to monitor the level of a water tank with an SR04 ; as it is not waterproof i assumed that it would die fairly quickly.
    So i ordered a DYP-ME007... but the last letter ("Y") means that it uses serial communication, so the ping Library doesn't apply.
    Bouncing from site to site i found the following code that @zboblamont refers to :

    #include <SoftwareSerial.h>
    
    SoftwareSerial mySerial =  SoftwareSerial(10,11); 
    
    #define echoPin 10
    #define trigPin 11
    
    unsigned int reading;
    byte readByte;
    byte read_buffer[4]; 
    byte crcCalc;
    word distance;
    String outText;
    
    void setup() {
      mySerial.begin (9600);
    
      Serial.begin (9600);
      Serial.println("start");
      for (byte loopstep = 0; loopstep <= 3; loopstep++) {
        read_buffer[loopstep] = 0;
      }
    }
    
    void loop() {
      if (mySerial.available() < 1) {
        return;  
      }
      readByte = mySerial.read();
      
      for (byte loopstep = 0; loopstep <= 2; loopstep++) {
        read_buffer[loopstep] = read_buffer[loopstep + 01];
      }
      read_buffer[03] = readByte;   
      if (read_buffer[00] != 0xff) {
        return;
      };
      crcCalc = read_buffer[00] + read_buffer[01] + read_buffer[02];
      if (read_buffer[03] != crcCalc) {
        return;
      };
      distance = (read_buffer[01] * 0xff) + read_buffer[02];
      outText = "bytes: ";
      outText = String(outText + read_buffer[00]);
      outText = String(outText + "+");
      outText = String(outText + read_buffer[01]);
      outText = String(outText + "+");
      outText = String(outText + read_buffer[02]);
      outText = String(outText + "+");
      outText = String(outText + read_buffer[03]);
      outText = String(outText + " = ");
      outText = String(outText + distance);
      outText = String(outText + " mm");
      
      Serial.println(outText);
    
      delay(1000);
    
      while (mySerial.available() > 0) {
         readByte = mySerial.read();
      }
    }
    

    Worked first shot

    Announcements

  • Weird behavior of email confirmation
    ben999B ben999

    @hek @mfalkvidd
    Incredible people !
    Not only you are top software and hardware men but you also manage the admin side of this website...
    Highest respect :crown:

    General Discussion

  • Alarm Clock
    ben999B ben999

    @mfalkvidd thank you very much for your detailed explanation !

    It does make a lot of sense

    And it compiles perfectly

    Thanks again for taking the time to correct and explain :)

    My Project

  • CNC PCB milling
    ben999B ben999

    very interresting post guys

    I have one of these in the garage (top of my head table is 10x15cm)

    I have never used it for pcb but @andrew tikkled my curiosity... very narrow tracks!

    For what it is worth and because i don't recall reading anything about it here, i have added endstops to my CNC
    It is well supported by the standard board supplied and GRBL takes care of it.
    I dont want to get involved in a fight between "Normaly Open" people and "Normaly Closed" people, so i wont tell you which i chose :D again GRBL and board can manage both
    https://www.ebay.com/itm/New-10PCS-Tact-Switch-KW11-3Z-5A-250V-Microswitch-3PIN-Buckle/173021165954?hash=item2848dd7982:g:xFsAAOSwGotWjjHo

    I get a very reliable "zero" on each axis. I actually home the 3 axis even after a tool change, just to be on the safe side

    It all runs on an old windows XP laptop. AutoCad for drawings, Dxf2GCode for... dxf to Gcode conversion :D and GCodeSender for feeding GCode to CNC.

    General Discussion

  • Smart doorbell
    ben999B ben999

    @adamf663 sorry for delay! I am focusing on mostly software at the moment. So nothing to show so far ;) i'll be posting as soon as the project moves forward again :+1: please read on !!!

    @MasMat thanks a lot for your suggestions. As suggested first it is more than probably a case of rights/permissions.

    There are many ways to launch a script at startup but in my case some deamons were started via "root" and some others via "user".
    As stated before, all worked perfectly when logged under "user" (pi).
    So, to summarise:

    • rc.local didn't work
    • crontab didn't work
    • .bashrc didn't work
      These might work in the end but i'm not brainy enought to get to it.

    Then came "systemctl" !
    First create a .service file

    $ sudo nano  /etc/systemd/system/doorbell.service
    
    [Unit]
    Description=My test service
    After=multi-user.target
    [Service]
    Type=simple
    Restart=always
    ExecStart=/usr/bin/python /home/pi/doorbell02.py
    [Install]
    WantedBy=multi-user.target
    #WantedBy=default.target    -> test this if previous doesn't work
    

    Reload all daemons to check if your new .service file is ok
    Then allow your new service file to be loaded at boot
    Last, check if loading worked. If status returns "active" then it's a win :+1:

    $ sudo systemctl daemon-reload
    $ sudo systemctl --user enable doorbell.service
    $ sudo systemctl --user start doorbell.service
    $ systemctl --user is-active doorbell.service
    

    Last step: systemctl loads these services at loggin by default (as in : enter user and password). I need it to start automaticaly with no human input. systelctl offers a way to load services without loggin for a given user :

    $ loginctl user-status pi
    

    Check status with

    $ loginctl user-status pi
    

    If status returns "linger: yes" then it's (once again) a win :+1:

    Thanks again @MasMat for suggesting paths to investigate

    That's it for now, i'll be back on the hardware point of view next time !

    My Project
  • Login

  • Don't have an account? Register

  • Login or register to search.
  • First post
    Last post
0
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular