Navigation

    • Register
    • Login
    • OpenHardware.io
    • Categories
    • Recent
    • Tags
    • Popular
    1. Home
    2. ben999
    3. Best
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    Best posts made by ben999

    • Automatic LED light - high WAF inside :)

      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 πŸ™‚

      posted in My Project
      ben999
      ben999
    • Alarm Clock

      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

      posted in My Project
      ben999
      ben999
    • RE: NRF24 Range

      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 ?

      posted in General Discussion
      ben999
      ben999
    • RE: Alarm Clock

      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
      }```
      posted in My Project
      ben999
      ben999
    • RE: CNC PCB milling

      @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?

      posted in General Discussion
      ben999
      ben999
    • RE: Alarm Clock

      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
      }```
      posted in My Project
      ben999
      ben999
    • RE: Can't link rfid node item

      @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 😒
      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...

      posted in OpenHAB
      ben999
      ben999
    • RE: Servo, dallas and Nano...

      @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

      posted in Hardware
      ben999
      ben999
    • RE: RPi 3 gateway problem

      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 ?

      posted in Troubleshooting
      ben999
      ben999
    • RE: πŸ’¬ Building a Raspberry Pi Gateway

      @Yveaux thanks a lot for your answer. Understanding linux is a slow and painful process πŸ˜†

      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! πŸ˜„

      posted in Announcements
      ben999
      ben999
    • Node battery voltage in openHAB iOS

      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

      posted in OpenHAB
      ben999
      ben999
    • Microwave oven (no kidding :D)

      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... πŸ™„ )

      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. 😁

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

      Thanks a lot for reading πŸ‘

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

      1.JPG

      2.JPG

      posted in Hardware
      ben999
      ben999
    • RE: πŸ’¬ Log Parser

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

      WOW that's huge !

      Thumbs up to those involved in that !!! Thanks a lot πŸ™‚

      posted in Announcements
      ben999
      ben999
    • RE: Alarm Clock

      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... ? πŸ˜†

      Would it fit the bill ? Any suggestions ?

      Thanks a lot !

      posted in My Project
      ben999
      ben999
    • RE: MySensors - Get Temperature value from another node through the Gateway

      @rejoe2 Dude!!! It worked! Awesome πŸ˜„ 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 πŸ˜„ as i wanted to understand both ways of sharing data between nodes
      Thank you so much for that πŸ‘

      posted in Development
      ben999
      ben999
    • RE: πŸ’¬ Distance Sensor

      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

      posted in Announcements
      ben999
      ben999
    • RE: Weird behavior of email confirmation

      @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 πŸ‘‘

      posted in General Discussion
      ben999
      ben999
    • RE: Alarm Clock

      @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 πŸ™‚

      posted in My Project
      ben999
      ben999
    • RE: CNC PCB milling

      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 πŸ˜„ 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 πŸ˜„ and GCodeSender for feeding GCode to CNC.

      posted in General Discussion
      ben999
      ben999
    • RE: Smart doorbell

      @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 πŸ‘ 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 πŸ‘

      $ 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 πŸ‘

      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 !

      posted in My Project
      ben999
      ben999
    • RE: CNC PCB milling

      That's the original designer of that shield :

      https://blog.protoneer.co.nz/arduino-cnc-shield/

      posted in General Discussion
      ben999
      ben999
    • IP phone and beacon

      Hi guys

      Long time no speak but still a MySensors fan !!

      My new project is a bit tougher than expected.

      Here is the thing: landline phones used to be analog type, with some 40v running across the wires... adding a beacon for noisy environment was a breeze, just plug it in and whenever a call comes in the beacon picks the signal and rings.

      My country has now moved to digital signal, IP i would say (please correct me if wrong terminology).
      So now the phone is connected at the back of optic fiber internet box (modem) via RJ45 plug.

      Needless to say that analog beacon has become useless. Beacon manufacturers have not yet moved their tech towards IP protocol.

      Have you ever bumped into that kind of challenge ? 😁

      I have a spare W5100 in the drawer... would it be able to access to the phone data, to check whether it's ringing ?

      Hope you get the picture and you can show me the way forward πŸ‘

      posted in General Discussion
      ben999
      ben999