Navigation

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

    ben999

    @ben999

    33
    Reputation
    149
    Posts
    1350
    Profile views
    1
    Followers
    0
    Following
    Joined Last Online
    Location France - Burgundy Age 45

    ben999 Follow

    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

    Latest posts made by 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: Smart doorbell

      Hi @MasMat

      Thanks a lot for your suggestions ! You DO talk like a linux ninja though ๐Ÿ˜„

      I'll have a go at these ๐Ÿ‘

      First let's try to understand :

      -fstab has multiple credentials currently

      what do you mean and how does this affect my "share"? I am very eager to understand. (although this part of my project is doing fine)

      did you have multiple pythons? (bbt.py, doorbell.py?)

      Sorry, no. My mistake. I tried to sanitise that post and forgot some dirt ๐Ÿ˜‰ only "doorbell.py running. Initial message corrected now.

      the launcher I believe has unnecessary lines (the changing directories)

      Ok i'll get that cleaned up

      crontab: why do "sudo crontab -e"? Would using just "crontab -e" use pi-users crontab and have less conflicting permissions?

      Ok i'll have a go as well, it makes sense. Trouble is i tend to put "sudo" everywhere so it kinda "forces" things to go as i planned them... not necessarily clever i agree... ๐Ÿ˜•

      I let you know tonight

      Would you have a suggestion on how to debug this script running in the background ? I tried pdb but it messes things up (starts multiple instances of doorbell.py... camera is constantly taking pictures, whole thing goes crazy) There must be some log of some sort that gets error message from programs running in background ?

      Thank you ever so much for spending time here. I'm really stuck now (been 2 weeks) and i really appreciate your effort here ๐Ÿ‘

      posted in My Project
      ben999
      ben999
    • RE: Smart doorbell

      My openhab is setup via files.

      I had some hard time discovering MQTT which was new to me and setging up openhab as it changed quite a lot since version 2.

      So here are my files, gin case it might help someone sometime :

      "items" file :

      Switch		doorBell01state	"Door Bell"              <alarm>	 {channel="mqtt:topic:mosquitto:doorBell01:doorBell01state"}
      

      "things" file :

      Bridge mqtt:broker:mosquitto "MySensorsGateway"@"Home" [host="192.168.1.20", port="1883", secure=false]
      {
      Thing topic doorBell01 "Door Bell"@"Front Gate" {
                      Channels:
                              Type switch :   doorBell01state         [stateTopic="doorbell/50/1/0/0/1", transformationPattern="MAP:onoff.map"]
              }
      }
      

      "rules" file :

      rule "frontgate bell ringing"
      when
               Item doorBell01state changed to ON
      then
              sendBroadcastNotification("Someone ringing at da gate!")
      end
      

      "map" file : (needed because i cant cope with types, numbers, decimals, values, ... so i tried many tricks and that one worked)

      0=OFF
      1=ON
      
      posted in My Project
      ben999
      ben999
    • Smart doorbell

      Hello World ๐Ÿ˜‰

      Here is my latest project, near completion: smart doorbell.

      Old raspberry 1B connected to the regular RaspiCam V1 and a push button.

      As soon as pushbutton is pressed :

      • RPi sends an MQTT message to network
      • Cam takes a picture and stores it to my local NAS
      • Gateway sends a notification all my portable devices connected to openHAB
      • RPi sends and email with picture attached

      This post has 2 goals :

      • share my findings. My house was until now still relying on openhab2 and mysensors binding. All working very happily. But there was no direct answer to get a raspberry to behave as a MySensor device and talk directly to the gateway. It was also time to move to openhab3. I was then advised to have a go at MQTT. So be it !!!
      • get some help linux-wise for completion of this project.

      I had to learn new tricks along the way... like mounting a network drive to the RPi. It's kind of linking/sharing a folder between my NAS and my RPi. If a file is dropped into that "mounted folder" it then appears on each device. Magic ๐Ÿ‘
      To do so edit your fstab file

      $ sudo nano /etc/fstab
      

      and add something like :

       //192.168.1.77/home/DoorBell     /home/pi/doorbell/ cifs vers=2.0,username=username,   password=passwordthatgoeswithit,credentials=/home/pi/doorbell .smbcred,noauto,x-systemd.automount 0 0
      

      I have tested this setup both at work and at home. I had to remove "credentials" and everything after at home as i could never get it to work (got some errors). I also had to change from "vers=3.0" to "vers=2.0". Googling never got me a real explanation...

      This is my python script, working as it should :

      import os
      import subprocess
      from datetime import datetime
      from gpiozero import Button
      
      button = Button(17)
      
      while True:
              button.wait_for_press()
              os.system('mosquitto_pub -h openhabian -t doorbell/50/1/0/0/1 -m "1"')
              time = datetime.now()
              filename = "capture-%04d%02d%02d-%02d%02d%02d.jpg" % (time.year, time.month, time.day, time.hour, time.minute, time.second)
              subprocess.call("raspistill -t 500 -o %s" % filename, shell=True)
      	subprocess.call("echo '' | mutt -s 'Someone ringing !' -i messageBody.txt myemailaddress@someprovider.com -a %s" % filename, shell=True)
              os.system('sudo /home/pi/movefile.sh')
              os.system('mosquitto_pub -h openhabian -t doorbell/50/1/0/0/1 -m "0"')
      

      The picture is stored with a convenient name (date and time) like so : capture-20210910-224322.jpg
      mutt is some simple, cool and efficient mailing program.
      messageBody.txt is a plain text file containing the body of the generic email.
      movefile.sh is a script that moves the jpg file from RPi's SD card up to NAS shared folder once the email has been sent.

      As i said previously it's all working as intended with

      $ python doorbell.py
      

      Next step is to get that python script to be launched at startup. A job for cron:

      $ sudo nano launcher.sh
      
      	#!/bin/sh
      	# launcher.sh
      	# navigate to home directory, then to this directory, then execute python script, then back home
      	cd /
      	cd home/pi
      	sudo python doorbell.py
      	cd /
      
      $ chmod 755 launcher.sh
      $ sh launcher.sh
      $ mkdir logs
      $ sudo crontab -e
      

      add this to file :

      @reboot sh /home/pi/launcher.sh >/home/pi/logs/cronlog 2>&1
      
      $ sudo reboot
      

      Quick check at logfile to make sure it all went well:

      $ cat logs/cronlog
      

      From then the email part of my script doesn't work anymore.
      Trouble with rights ?

      ps aux
      

      returns that launcher.sh belongs to root but python script belongs to pi :

      root       475  0.0  0.0      0     0 ?        S    16:51   0:00 [cifsd]
      root       500  0.0  0.6   7932  2300 ?        Ss   16:51   0:00 /usr/sbin/cron -f
      root       502  0.0  0.6   9452  2384 ?        S    16:51   0:00 /usr/sbin/CRON -f
      root       506  0.0  0.3   1924  1148 ?        Ss   16:51   0:00 /bin/sh -c sh /home/pi/launcher.sh >/home/pi/logs/cronlog 2>&1
      root       511  0.0  0.2   1924  1108 ?        S    16:51   0:00 sh /home/pi/launcher.sh
      root       513  1.5  2.5  34348  9728 ?        Sl   16:51   4:25 python doorbell02.py
      root       514  0.0  0.3  27640  1364 ?        SLsl 16:51   0:00 /usr/sbin/rngd -r /dev/hwrng
      root       525  0.0  0.4   4292  1588 tty1     Ss+  16:51   0:00 /sbin/agetty -o -p -- \u --noclear tty1 linux
      root       527  0.0  0.4   6600  1852 ?        Ss+  16:51   0:00 /sbin/agetty -o -p -- \u --keep-baud 115200,38400,9600 ttyAMA0 vt220
      root       757  0.0  1.6  12224  6228 ?        Ss   16:53   0:00 sshd: pi [priv]
      pi         760  0.0  1.8  14584  7072 ?        Ss   16:53   0:00 /lib/systemd/systemd --user
      

      Does it ring a bell to anyone ?

      Thanks a lot for your help guys!

      posted in My Project
      ben999
      ben999
    • RE: Raspberry as a node (bis)

      @Yveaux ๐Ÿ‘ thank you

      ๐Ÿ˜„ here you are talking once again a weired language ๐Ÿ˜„

      Ok i'll dig what MQTT can do for me. How does the piece of data (someone pushed the doorbell button) gets from RPi to openhab ? Does it stay local within the LAN (and gets directly to my gateway) or does it have to travel through internet up to openhab and down again to my gateway (remember, my bell has to ring) ?

      So last question just to be sure : it is not common practice to use RPi as a node ? And there is no "sketch" ready made that can be tweaked ?

      Thanks a lot for your time, i really appreciate it ๐Ÿ˜‰

      posted in Hardware
      ben999
      ben999
    • RE: Raspberry as a node (bis)

      @Yveaux hi

      Thanks a lot for your reply ๐Ÿ‘

      Slight misunderstanding here ๐Ÿ˜‰

      Raspberry will be connected to LAN to transfer picture to NAS, probaly via wifi (or wired if i decide to go down the PoE road...)

      But i also want the RPi to be connected to openHab in order to send notification of "front gate button pushed" via MySensors so i can get the doorbell to ring AND a broadcast message from openHab.

      About security:
      My router offers me an option of NOT giving internet access to any device while still being connected to LAN. Is that safe enough ?

      posted in Hardware
      ben999
      ben999
    • Raspberry as a node (bis)

      Hi all

      Not posting doesn't that mean i've lost interest ๐Ÿ˜

      My house relies more and more on MySensors and openHab... great team, i'm delighted !

      Time for a new challenge : "smart" door bell.

      What is on my mind : old raspberry with its cam hidden in the front fence pillar. As soon as the doorbell push button is pushed, the bell rings (inside the house) but also a picture is taken and (at the beginning at least) is stored onto my local NAS. Then, if i'm not home i would get a broadcast message from OH.

      That brings me to the following question : can a Raspberry Pi be hooked to a NRF module and behave like a node ?

      That post (https://forum.mysensors.org/topic/6949/raspberry-pi-zero-as-sensor-node) brought me a security issue : smart devices connected to LAN can become a weakness

      Other than that i would connect an Arduino to the RPi but then that looks a bit over-complicated...

      Thanks for your help people ! ๐Ÿ‘

      posted in Hardware
      ben999
      ben999
    • RE: Piezzo siren/alarm

      @fotofieber DC+ one output is really poor and voltage has no impact on noise. I have tested with up to 6S LiPo and there's absolutely no gain as compared to 5V DC

      AC+ two outputs is a game changer! Much louder right from +/-5V and really a killer @ +/-12V.

      So that's it: the first iteration of this project will go for a step-up converter from 5V up to 12V for the piezo speaker.

      Thanks folks!

      EDIT: could someone suggest a MOSFET (or transistor) that could be used in lieu of the huge (and probably over-sized) TIP120 (that where there, waiting in the drawer ๐Ÿ™‚ ). Through-hole is my league. SMD is a bit of a struggle (welding, machining pcb, ...)

      Thanks again ๐Ÿ˜ƒ

      posted in Hardware
      ben999
      ben999
    • RE: Piezzo siren/alarm

      @fotofieber gosh that a good analysis ๐Ÿ‘ that makes a lot of sense
      Then i can picture things better:

      • one output with 0 et +5V is considered as DC
      • two output pulling differentially -5V to +5V... looks like a sin curbe... so it's AC !

      Breadboard is out and still cabled, i'll have a go asap and confirm

      Thanks again for your knowledge

      posted in Hardware
      ben999
      ben999