Navigation

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

    ben999

    @ben999

    34
    Reputation
    157
    Posts
    1353
    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: Microwave oven (no kidding :D)

      @skywatch great, thanks a lot for your suggestion. A bit of research on the internet educated me about these diodes ๐Ÿ˜„ looks like they already exist on the board that carries the relay. However, i deeply thank you for the info. This forum and internet in general is such a powerful tool ๐Ÿ‘

      @ejlane your concern is fully justified ๐Ÿ‘ i also come from an engineering background and i like to think "worse case scenario".
      The more one look the more one find that the very vast majority or microwave ovens work the same way : there are 3 industrial switches built in the door lock. 2 of them are cabled on the "power side", one is for signaling ("software side"). So we are pretty safe on that matter.
      But you are so right about safety. Magnetron do emitt dangerous waves and capacitors and stuff packed in the oven can be deadly because of high voltage.

      Thanks both for suggestions. I will come back with updated sketches and beg for advice once more ๐Ÿ˜‰

      posted in Hardware
      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: MQTT losing messages...

      @JeeLet
      @OldSurferDude

      Thank you both ๐Ÿ‘

      My Raspberry 3 does it all :

      • gateway with nrf24 module (standard one)
      • mysensors MQTT gateway
      • Mosquitto broker

      MQTT Explorer has been installed on my fav laptop and it helps seeing clearer.

      Nevertheless i cannot reproduce the errors.

      I have multiple points of view:

      • node : using arduino ide serial monitor
      • mysensors gateway: using tail log in a terminal window
      • openHab : using tail log in an internet explorer window
      • MQTT explorer : in its own window

      I can sent MQTT messages from different devices :

      • iOS openhab from my phone
      • openhab (basic UI) from an internet explorer window
      • MQTT explorer (messages can be made-up, very cool tool)
      • terminal window (linux laptop via ssh)

      The less reliable way of sending MQTT message is via terminal : after 2 to 10 succesfull messages it then stops working. At first, node receives messages and processes them (servo moves). But after a few messages, node doesn't receive anymore. MQTT Explorer shows the change of state of the topic but message doesn't go anyfurther... no other monitor show a change.

      @OldSurferDude i'm not sure i understand

      Each node should be sending messages to its own topic.

      Can the mysensor gateway subscribe to more than one topic (which is mysensors-in at the mo) ?

      Thanks a lot for helping me through ๐Ÿ˜Š

      posted in OpenHAB
      ben999
      ben999
    • RE: MQTT losing messages...

      @JeeLet thanks a lot for your message

      You're right :

      • openhab 3
      • Raspberry Pi 3 MQTT gateway with Mosquitto
      • arduino nodes
      • nRF24 network

      TBH i don't know where to start, so difficult to point a finger...

      posted in OpenHAB
      ben999
      ben999
    • MQTT losing messages...

      Hi guys,

      Long story cut short :

      I've had lots of "temporary gone bad nodes" since migrating from serial to mqtt.

      Nodes that are normally working fine but then stop responding (most annoying being the one driving the garage door motor ๐Ÿ˜ฑ i now keep a key anytime with me instead of just relying on openHab...). A reboot cures it.

      So i decided to design a simple logger with arduino + sd card + rtc.

      Beside that i am also designing an automatic cat flap locking node, so cats dont go out at night. As i dont want any rtc on that node, i rely on time supplied by controller with requestTime(). So here i am trying to understand how to send that request to controller via mqtt by sending publications...

      That's how i discovered that many publications are lost.

      What do you suggest to investigate further ? I might have reached my limits... ๐Ÿ˜ฌ some help would be welcome ๐Ÿ‘

      Thanks a lot ๐Ÿ˜Š

      posted in OpenHAB
      ben999
      ben999
    • RE: nrf24+ module with stick antenna

      @skywatch oh great ๐Ÿ‘ thanks for that !

      by removing the smd then the signal becomes "compatible" with a 2.4ghz stick antenna ?

      or shall i go with wire and adjust length ?

      Thanks everyone ๐Ÿ™‚

      posted in Hardware
      ben999
      ben999
    • RE: nrf24+ module with stick antenna

      @NeverDie thanks a lot for taking so much time for your answer ๐Ÿ‘

      Your explainations pushed my thinking a bit further. I now understand that i can't just solder a 2.4ghz stick antenna in-lieu of a "trace" antenna just because it is a 2.4ghz board... am i right ?

      The main reason for my post is that i need to have a remote antenna.
      And i also wanted to keep clear of Power Amplified modules as their power consumption is too high for my needs (tiny LiPo and solr panel)

      And i also wanted to use what's in the drawer ๐Ÿ˜‰

      I shall then turn to nrf modules with external antenna. Usual one are difficult to get now. But it seems there are newer ones out there (at least their layout seems new to me) :

      nrf.JPG

      Anyone tried yet ?

      Anyway, thanks a lot for making things clearer ๐Ÿ˜Š

      posted in Hardware
      ben999
      ben999
    • nrf24+ module with stick antenna

      Hi Guys,

      I would like to connect a stick antenna to a basic nrf24L01+ module.

      Please note that i do not need any additional range.

      The reason i'm asking is because the nrf is surrounded by metal, copper traces and battery...

      So getting the antenna out of the housing might help.

      I have an SMA connector handy and a stick antenna as well.

      My main question is about soldering the coax cable :

      hack.JPG

      1 -shall i cut the trace as stated in numerous hacksites ?
      2 - shall i solder the inner conductor where the blue arrow is ?
      3 - shall i solder the outer connector (shield?) where the red arrow is ? or is it best to scratch underside of board and solder straight into ground plane ? but then that reveals more inner connector length, thus next question...

      What is the importance of the length of "naked" inner conductor where the insulation will be cut ?

      Thanks a lot for your help, comments of any sort are welcome ๐Ÿ˜‰

      posted in Hardware
      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: 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