Navigation

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

    freynder

    @freynder

    33
    Reputation
    61
    Posts
    814
    Profile views
    1
    Followers
    0
    Following
    Joined Last Online

    freynder Follow

    Best posts made by freynder

    • Using state machines for MySensors sketch

      As I have been struggling in the past to coordinate states in my sketches, I recently started using state machines. I'm very happy with the result and thought I might share it here should anyone feel interested.

      The code can be found here:
      https://github.com/freynder/LowPowerButtons

      It uses the Automaton library as a framework to run the state machine logic and let the machines interact.
      https://github.com/tinkerspy/Automaton
      There is a small learning curve but I think it's worth it.

      The example sketch consists of a binary switch sensor that uses 2 state machines:

      • SleepyMachine: Will remain awake during a short time and try to detect any button presses. When a timeout is reached it will turn the device into sleep mode. When waking up it will try to find out why and if a button may have been pressed, it will wait for the button to be handled or return to sleep after a short timeout.
      • MySensorsSender: contains logic to send MySenors messages and handle acknowledgement + implements a retry mechanism with timeouts. The retry mechanism is probably redundant as RFM69 performs retries on the transport level already, but it is available should you want it.
      • Button (provided by the framework): handles button presses and debounce logic.

      All the sketch logic is contained within the state machine logic and their interactions; the main loop is very minimal.

      I also used state machines in another node for eliminating doubles while handling RF communications, I can share that as well if interested.

      posted in Development
      freynder
      freynder
    • RE: ๐Ÿ’ฌ E73-2G4M04S Breakout

      Boards arrived today. They look good and initial testing is succesful.

      posted in OpenHardware.io
      freynder
      freynder
    • RE: Pin Change Interrupt on "any" pin.

      @DavidZH

      I have been working on a similar problem lately and just noticed your post. I also tried using libraries at first, but ran into issues due to bouncing signals from the buttons. The pin change interrupt service routine tried to detect which button was pressed, but since the signal was bouncing, button presses were missed. The system would wake up but not call the appropriate callback function associated with the pin.

      I put together a sketch that works for me. It involves setting up the change pin interrupts, detecting which button is pressed and some provisions for debouncing the signal. It uses a small hack to leave the timed sleep function on pin change interrupts. I did not have trouble entering sleep like you did.

      Please note that this sketch uses the current MySensors development branch.

      The sketch is below, I hope it helps.

      /**
       * The MySensors Arduino library handles the wireless radio link and protocol
       * between your home built sensors/actuators and HA controller of choice.
       * The sensors forms a self healing radio network with optional repeaters. Each
       * repeater and gateway builds a routing tables in EEPROM which keeps track of the
       * network topology allowing messages to be routed to nodes.
       *
       * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
       * Copyright (C) 2013-2015 Sensnology AB
       * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
       *
       * Documentation: http://www.mysensors.org
       * Support Forum: http://forum.mysensors.org
       *
       * This program is free software; you can redistribute it and/or
       * modify it under the terms of the GNU General Public License
       * version 2 as published by the Free Software Foundation.
       *
       *******************************
       *
       * DESCRIPTION
       *
       * Interrupt driven binary switch example with dual pin change interrupts
       * Author: Francis Reynders
       * MySensors does not support pin change interrupts currently. This sketch
       * initializes pin change interrupts and combines it with MySensors sleep
       * functions. Some hacking is required to get out of the hwInternalSleep loop.
       * Tested with atmega328p standalone but should work with Arduino Nano/Pro MiniCore
       * Uses RFM69 for transport.
       *
       * Based on original work by:
       * Author: Patrick 'Anticimex' Fallberg
       * Connect one button or door/window reed switch between
       * digitial I/O pin 3 (BUTTON_PIN below) and GND and the other
       * one in similar fashion on digital I/O pin 2.
       * This example is designed to fit Arduino Nano/Pro Mini
       *
       */
      
      // Enable debug prints to serial monitor
      #define MY_DEBUG
      
      // Enable and select radio type attached
      //#define MY_RADIO_NRF24
      #define MY_RADIO_RFM69
      #define MY_RFM69_ENABLE_ENCRYPTION
      #define MY_RFM69_FREQUENCY RF69_433MHZ // Set your frequency here
      //#define MY_IS_RFM69HW // Omit if your RFM is not "H"
      //#define MY_RFM69_NETWORKID 100  // Default is 100 in lib. Uncomment it and set your preferred network id if needed
      #define MY_RF69_IRQ_PIN 2
      #define MY_RF69_IRQ_NUM 0
      #define MY_RF69_SPI_CS 10
      //#define MY_NODE_ID 2
      
      #include <MySensors.h>
      
      #define SKETCH_NAME "Binary Sensor"
      #define SKETCH_MAJOR_VER "2"
      #define SKETCH_MINOR_VER "0"
      
      #define PRIMARY_CHILD_ID 3 // PD3
      #define SECONDARY_CHILD_ID 4 // PD4
      
      #define PRIMARY_BUTTON_PIN 3   // Arduino Digital I/O pin for button/reed switch
      #define SECONDARY_BUTTON_PIN 4 // Arduino Digital I/O pin for button/reed switch
      
      #define DEBOUNCE_INTERVAL 100
      #define DEBOUNCE_COUNT_THRESHOLD 15 // required consecutive positive readings
      #define PREVENT_DOUBLE_INTERVAL 400
      
      #define SLEEP_TIME (6 * 60 * 60 * 1000ul) // Check battery every 6 hours
      
      #define BATTERY_MAX_MVOLT 2900
      #define BATTERY_MIN_MVOLT 2300
      
      // Change to V_LIGHT if you use S_LIGHT in presentation below
      MyMessage msg(PRIMARY_CHILD_ID, V_LIGHT);
      MyMessage msg2(SECONDARY_CHILD_ID, V_LIGHT);
      
      bool triggered = false;
      uint32_t lastWakeup = 0;
      uint16_t lastBatteryVoltage = 0u;
      
      enum wakeup_t {
        WAKE_BY_TIMER,
        WAKE_BY_PCINT0,
        WAKE_BY_PCINT1,
        WAKE_BY_PCINT2,
        UNDEFINED
      };
      
      volatile wakeup_t wakeupReason = UNDEFINED;
      
      // Pin change interrupt service routines
      ISR (PCINT0_vect) // handle pin change interrupt for PCINT[7:0]
      {
        wakeupReason = WAKE_BY_PCINT0;
        _wokeUpByInterrupt = 0xFE; // Dirty hack to get out of MySensors sleep loop
      }
      
      ISR (PCINT1_vect) // handle pin change interrupt for PCINT[14:8]
      {
        wakeupReason = WAKE_BY_PCINT1;
        _wokeUpByInterrupt = 0xFE; // Dirty hack to get out of MySensors sleep loop
      }
      
      ISR (PCINT2_vect) // handle pin change interrupt for PCINT[23:16]
      {
        wakeupReason = WAKE_BY_PCINT2;
        _wokeUpByInterrupt = 0xFE; // Dirty hack to get out of MySensors sleep loop
      }
      
      void pciSetup(byte pin)
      {
        *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // enable pin
        PCIFR  |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
        PCICR  |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
      }
      
      void setup()
      {
        CORE_DEBUG(PSTR("Started\n"));
      
        // Workaround to use center frequency
        //_radio.setFrequency(RF69_EXACT_FREQ);
        #ifdef MY_IS_RFM69HW
          _radio.setPowerLevel(16); // 10dBm for RFM69HW
        #else
          _radio.setPowerLevel(28); // 10dBm for RFM69W
        #endif
      
        pinMode(PRIMARY_BUTTON_PIN, INPUT);           // set pin to input
        digitalWrite(PRIMARY_BUTTON_PIN, INPUT_PULLUP);       // turn on pullup resistors
      
        pinMode(SECONDARY_BUTTON_PIN, INPUT);           // set pin to input
        digitalWrite(SECONDARY_BUTTON_PIN, INPUT_PULLUP);       // turn on pullup resistors
      
        // Set up Pin change interrupt
        pciSetup(PRIMARY_BUTTON_PIN);
        pciSetup(SECONDARY_BUTTON_PIN);
      }
      
      void presentation()
      {
      	// Send the sketch version information to the gateway and Controller
      	sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER "." SKETCH_MINOR_VER);
      
      	// Register binary input sensor to sensor_node (they will be created as child devices)
      	// You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage.
      	// If S_LIGHT is used, remember to update variable type you send in. See "msg" above.
      	present(PRIMARY_CHILD_ID, S_LIGHT);
      	present(SECONDARY_CHILD_ID, S_LIGHT);
      }
      
      void loop()
      {
        // Unset value from dirty hack to get out of sleep loop (set in interrupt)
        _wokeUpByInterrupt = INVALID_INTERRUPT_NUM;
      
        CORE_DEBUG(PSTR("Woken up\n"));
        if(wakeupReason == WAKE_BY_PCINT2) {
          wakeupReason = UNDEFINED;
          handleButtons();
        }
        handleBatteryLevel();
      
        CORE_DEBUG(PSTR("Going to sleep...\n"));
        sleep(SLEEP_TIME);
      }
      
      void handleButtons()
      {
        static uint8_t button1Count;
        static uint8_t button2Count;
        static uint32_t started, ended, delta;
      
        CORE_DEBUG(PSTR("Detecting buttons START\n"));
      
        button1Count = 0;
        button2Count = 0;
      
        // Try and detect which key during max DEBOUNCE_INTERVAL
        started = millis();
        while(millis() - started < DEBOUNCE_INTERVAL) {
          if(digitalRead(PRIMARY_BUTTON_PIN) == LOW) {
            button1Count++;
          } else {
            button1Count=0;
          }
          if(digitalRead(SECONDARY_CHILD_ID) == LOW) {
            button2Count++;
          } else {
            button2Count=0;
          }
          if(button1Count > DEBOUNCE_COUNT_THRESHOLD) {
            CORE_DEBUG(PSTR("Button 1 pressed\n"));
            send(msg.set(1));
            break;
          }
          if(button2Count > DEBOUNCE_COUNT_THRESHOLD) {
            CORE_DEBUG(PSTR("Button 2 pressed\n"));
            send(msg2.set(1));
            break;
          }
        }
        CORE_DEBUG(PSTR("Detecting buttons END\n"));
      
        // This section prevents detecting additional bounces
        ended = millis();
        if(ended > started) {
          delta = ended - started;
          if(delta < PREVENT_DOUBLE_INTERVAL) {
            CORE_DEBUG(PSTR("Waiting: %d \n"), PREVENT_DOUBLE_INTERVAL - delta);
            wait(PREVENT_DOUBLE_INTERVAL - delta); // In case the signal still is not stable after detection
          }
        }
      }
      
      void handleBatteryLevel()
      {
        static uint16_t voltage;
        static uint8_t batteryPct;
      
        CORE_DEBUG(PSTR("Checking Battery BEGIN\n"));
        voltage  = hwCPUVoltage();
        CORE_DEBUG(PSTR("Voltage: %d\n"), voltage);
      
        // Process change in battery level
        if(lastBatteryVoltage == 0 || lastBatteryVoltage != voltage) {
          lastBatteryVoltage = voltage;
          if(voltage < BATTERY_MIN_MVOLT) {
            batteryPct = 0;
          } else {
            batteryPct = 100 * (voltage - BATTERY_MIN_MVOLT) / (BATTERY_MAX_MVOLT - BATTERY_MIN_MVOLT);
          }
          sendBatteryLevel(batteryPct);
        } else {
          CORE_DEBUG(PSTR("No Change\n"));
        }
      
        CORE_DEBUG(PSTR("Checking Battery END\n"));
      }
      
      
      posted in General Discussion
      freynder
      freynder
    • RFM69 433Mhz ISM band

      Hi,

      I recently started experimenting with MySensors which works great so far.

      While checking the code for the RFM69 driver, I noticed that when frequency setting MY_RFM69_FREQUENCY is set to RF69_433MHZ, the driver will initialize the frequency register (RegFrf) to 0x6C4000 which corresponds to exactly 433.00 Mhz (according to the formula in the datasheet).

      However, the 433 ISM band is defined as (https://en.wikipedia.org/wiki/ISM_band) 433.05 MHz - 434.79 MHz with 433.92 MHz center frequency. So it looks like the driver sets a frequency just outside of the band. Would it not be better to initialize with the center frequency?

      I would appreciate any feedback as I want to make sure to comply with regulations.

      posted in Development
      freynder
      freynder
    • RE: ๐Ÿ’ฌ ESP32 MySensors Gateway V4.4

      Assembled the board and some issues came up. Updated project description and added a few images. Will test in more detail soon.

      posted in OpenHardware.io
      freynder
      freynder
    • RE: STM32?

      I just finished my first low power test implementation for STM32: a low power dual button sensor using RFM69 and external interrupts. It seems to work very well so far. My multimeter shows 0.01 mA sleep current, but I'm not sure how well this can be trusted.

      The sketch can be found here: https://github.com/freynder/LowPowerButtons
      It uses platformio IDE directory structure.

      The modifications to MySensors (not complete/nicely implemented yet) can be found here: https://github.com/freynder/MySensors/tree/stm32f1_sleep
      I hope to find time in the near future to clean it up + implement support for interrupts and contribute it to the project if not already available by then.

      posted in General Discussion
      freynder
      freynder
    • RE: Understanding syntax

      Hi @ricorico94 ,

      This is basic C syntax so I would recommend reading up on C language basics if you would like to have a better understanding.

      The #define macro here is a preprocessor macro. Any N_ELEMENTS(array) occurrences get replaced by (sizeof(array)/sizeof((array)[0])). array is a variable and gets replaced with the provided value.

      So in this case, the preprocessor will change

      N_ELEMENTS(SENSOR_ANALOG_PINS)
      

      to

      (sizeof(SENSOR_ANALOG_PINS)/sizeof((SENSOR_ANALOG_PINS)[0]))
      

      before compilation.

      So it will take the total byte size of the array (which is already defined at that point) divided by the byte size of the first element in the array, thus providing the number of elements in the array.

      Another way to code the statements without the #define would be to replace that part in the code yourself (like I did above).

      posted in Development
      freynder
      freynder
    • RE: STM32?

      @ooznerol : it's been a while but I've had some issues with this as well. Here are some pointers that may help you:

      If I remember correctly, it depends on the upload method which may set particular build flags. In my platformio configuration for example, I'm setting the following build flags:
      build_flags = -DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DSERIAL_USB -DGENERIC_BOOTLOADER when using the stlink upload method. CONFIG_MAPLE_MINI_NO_DISABLE_DEBUG was necessary to preserve the SWD pins and SERIAL_USB creates a virtual UART for serial output to the USB port. If Serial_USB is not set then the hardware serial is being used. Which one? According to https://github.com/rogerclarkmelbourne/STM32duino-bootloader/issues/8 it depends on the fact that you are using a bootloader or not, so serial1 (PA9/PA10) or serial2 (PA2/PA3).

      Also, if you experience issues with the USB connection, check the pullup resistor on D+ as indicated in http://wiki.stm32duino.com/index.php?title=Blue_Pill .

      I'm not sure what IDE/upload method/board library you are using. In any case, watching the output during upload to find out the build flags may be useful. If that does not help, then pls send me the details of your setup and I will try to test it myself.

      tinwinaung created this issue in rogerclarkmelbourne/STM32duino-bootloader

      closed Using Serial UART1 #8

      posted in General Discussion
      freynder
      freynder
    • RE: ๐Ÿ’ฌ STM32 Sensor Node

      Thank you. Good idea about the antenna. I updated everything to V3 which contains a much better layout, clear markings and an u.FL connector. I was quick to order V2 prototype boards yesterday, I guess I will need to order another batch for V3 now ๐Ÿ˜‰

      posted in OpenHardware.io
      freynder
      freynder
    • RE: RFM69 433Mhz ISM band

      Thank you all. I changed the register values directly in the RFM69 driver and it all seems to work.

      Hopefully a new release will soon include this (as well as the ATC feature). Also, local legislation specifies maximum transmission power as 10mW for the 433 band, so I included the code below in my sketch. It would be good to be able to configure this in the future as well.

      #ifdef MY_IS_RFM69HW
        _radio.setPowerLevel(16); // 10dBm for RFM69HW
      #else
        _radio.setPowerLevel(28); // 10dBm for RFM69W
      #endif
      
      posted in Development
      freynder
      freynder

    Latest posts made by freynder

    • RE: ๐Ÿ’ฌ E73-2G4M04S Breakout

      Sorry, only saw your message now. If still needed, I do have a few boards left.

      posted in OpenHardware.io
      freynder
      freynder
    • RE: ๐Ÿ’ฌ STM32 Sensor Node

      Power consumption should be comparable to the blue pill with leds and regulator removed. Never got around measuring it myself but here are some results for the bluepill: https://www.stm32duino.com/viewtopic.php?f=3&t=658&start=40 , stating 13ยตA in STOP mode.
      Also note that last time I checked, low power was not supported in MySensors for these MCU's so you would need to add it in yourself.

      posted in OpenHardware.io
      freynder
      freynder
    • RE: ๐Ÿ’ฌ STM32 Sensor Node

      @ian1scott: sorry for the late reply. The part references can be found in the Fab layer in the kicad file.

      posted in OpenHardware.io
      freynder
      freynder
    • RE: openHAB 2.2 binding

      @timo said in openHAB 2.2 binding:

      I continue to hope for an integration in the main repository. ๐Ÿ˜‰

      Hi @TimO,
      What is preventing this? I'm willing to help if needed.

      posted in OpenHAB
      freynder
      freynder
    • RE: ๐Ÿ’ฌ ESP32 MySensors Gateway V4.4

      Version 4.2 was just published. The board now also contains breakout headers for I2C devices (temperature sensors such as Si7021, HTU21D, SHTT71 and BME280) and a headers for a RXB6 RF 433Mhz receiver. Not tested yet.

      posted in OpenHardware.io
      freynder
      freynder
    • RE: ๐Ÿ’ฌ ESP32 MySensors Gateway V4.4

      After testing the board for a few weeks I implemented a major redesign, marked as V4. Not tested yet.

      Changes:

      • Changed headers to XH2.54 connectors for leds and buttons
      • Added secondary regulator to power RF modules
      • Changed RFM69 footprints to remove unused pads
      • Changed CHG340G chip to CHG340C, eliminating the crystal
      • Relayed all traces for cleaner design
      • Added capacitors at USB input power
      • Added second capacitor for decoupling at RFM69 modules
      posted in OpenHardware.io
      freynder
      freynder
    • RE: Recommendation for PCB fab?

      @diogoc said in Recommendation for PCB fab?:

      JLCPCB made good and cheap pcbs

      I second that. Especially if you can combine a few PCBs in one order it is very interesting.

      posted in General Discussion
      freynder
      freynder
    • RE: Is the 32-bit ATSAML10 the ATMEGA328P killer that we've been waiting for?

      @yveaux and @scalz

      Thanks for confirming. So only Clark's core is supported at the moment.

      It would be interesting to support the official STM32 core as they provide low power functions. I will do some experiments.

      posted in Hardware
      freynder
      freynder
    • RE: Linux gateway don't receive Ack

      @mfalkvidd said in Linux gateway don't receive Ack:

      @freynder but if RSSI is excellent, it means someone else must be sending and the channel isn't free. So maybe the correct value is returned anyway in your calculation example (but the comparison is still strange)

      Indeed you were right. I had a wrong understanding on how RSSI was measured. It appears to be an indication of "the amount of energy available within the receiver channel bandwidth", so if nobody is sending it will be low.

      posted in Troubleshooting
      freynder
      freynder
    • RE: Linux gateway don't receive Ack

      @rozpruwacz Ok, got it now. Thank you very much.

      posted in Troubleshooting
      freynder
      freynder