Request for help building a 433Mhz sender node



  • Hi all,

    First of all my compliments for this fantastic framework, I'm new here and I was trying to improve the wheel many times but using "mysensors" feels like the right way to do things (tm).

    I like to connect different things to my domotica system, this time I'm trying to create a 433Mhz sender. I know there are some examples but they don't seem to fit my needs.

    What I like to do is create a general 433Mhz sender based on the NewRemoteTransmitter library, the parameters to the sendUnit function should come from the controller (mind the 24byte limit, parameters should include: address,unit and payload all encoded in a single VAR1 payload)

    I have some questions, perhaps one of you can help me?

    • Is VAR1 for the payload a good choice?
    • What is the best way to tranport a multi value payload? (address,unit,payload)
    • 433Mhz also supports DIM levels, ranged from 0 to 15, is there an easy method to scale this from 0 to 100?

    Many questions for a new user I know, hope to see some feedback 🙂

    current example code

    // 433Mhz transmitter for mysensors.org
    
    #include <MySensor.h>
    #include <SPI.h>
    #include <NewRemoteTransmitter.h>
    
    #define SN "RF433Sender"
    #define SV "1.0.2"
    #define TRANSMITTER_PIN 8
    #define RF433_CHILD_ID 1
    
    MySensor gw;
    MyMessage msg(RF433_CHILD_ID, V_VAR1);
    
    void setup()
    {
      // Attach method for incoming messages
      gw.begin(incomingMessage, AUTO, true);
    
      // Send the sketch version information to the gateway and Controller
      gw.sendSketchInfo(SN, SV);
    
      // Register all sensors to gw (they will be created as child devices)
      gw.present(RF433_CHILD_ID, S_IR);
    }
    
    void loop()
    {
      gw.process();
    }
    
    void incomingMessage(const MyMessage &message) {
      if (message.type == V_VAR1 ) {
        unsigned long address = 231337; // TODO hardcoded
        int unit = 0; // TODO hardcoded
        bool payload = message.getBool();
    
        /*
        Serial.println(address);
        Serial.println(unit);
        Serial.println(payload);
        */
    
        NewRemoteTransmitter transmitter(address, TRANSMITTER_PIN, 260, 3);
        transmitter.sendUnit(unit, payload ? 1 : 0);
      }
    }
    


  • You can use Var1, the easiest way is to keep the sended string always the same length so you can cut in the variable in pieces: http://www.arduino.cc/en/Tutorial/StringRemove

    to change 0-100 to 0-15

    int kakuDimLevel = (dimLevel / 100) * 15


  • Contest Winner

    @cdr

    or just use the map( ) function:

    radioDimValue = map(veraDimValue, 0, 100, 0, 15)
    

    will return your veraDimValue (from 0 to 100) scaled for the radio (from 0 to 15).



  • @BulldogLowell Nice I didn't know that. But what happens if the dimvalue is higher that 100? does it still translate to 100/15?



  • Thanks for the replies, both solutions regarding dim level are nice and at least save me time.

    @Sweebee I was thinking to use a VAR1 like "a=12345,u=1,p=0" maybe not the most elegant solution, the fixed string option feels too complex, having to pad leading zero's. But then again a simple "123456,4,0" should work too.

    I guess it's not possible to send multi VAR payloads? That would be the most elegant option I guess. Maybe mysensors 2.0? 🙂


  • Contest Winner

    @Sweebee

    the web link I provided will tell you what happen if you go out of bounds on the number you want to map, but if you don't have a upper boundary on veraDimValue, but you need it, well just use the min( ) function:

    radioDimValue = min(map(veraDimValue, 0, 100, 0, 15), 15);
    

    and it won't return an int higher than 15 😉


  • Admin

    You can transfer custom data structures using this:
    https://github.com/mysensors/Arduino/blob/master/libraries/MySensors/MyMessage.cpp#L171

    Which means you can send C-structs between sensors or all the way to the controller.
    The payload will be expanded to hex codes over serial line. E.g. a001c0fc...
    The only problem (on the controller side) is that you have to take care of about endianness (for multi byte data types) and how the AVR compiler packs the structs.



  • Thanks for the replies, I got a working sample which can send and receive 433 Mhz signals.

    My skills don't include advanced C code, so this is the best I can do 🙂 It's working for me, so I'll share my work;

    #include <SPI.h>
    #include <MySensor.h>
    #include <NewRemoteReceiver.h>
    #include <NewRemoteTransmitter.h>
    
    //project
    #define SN "RF433Tranceiver"
    #define SV "1.2.2"
    
    //children
    #define CHILD_ID_RF433_RECEIVER 0
    #define CHILD_ID_RF433_TRANSMITTER 1
    
    //pins
    #define RF433_TRANSMITTER_DIGITAL_PIN 8
    #define RF433_RECEIVER_DIGITAL_PIN 3
    #define INTERRUPT RF433_RECEIVER_DIGITAL_PIN-2
    
    String combined_received_code;
    String lastcombined_received_code;
    
    MySensor gw;
    MyMessage msgReceive(CHILD_ID_RF433_RECEIVER, V_IR_SEND);
    MyMessage msgTransmit(CHILD_ID_RF433_TRANSMITTER, V_VAR1);
    
    void setup() {
      gw.begin(incomingMessage, AUTO, true);
      gw.sendSketchInfo(SN, SV);
      gw.present(CHILD_ID_RF433_RECEIVER, S_IR);
      gw.present(CHILD_ID_RF433_TRANSMITTER, S_IR);
    
      NewRemoteReceiver::init(INTERRUPT, RF433_RECEIVER_DIGITAL_PIN, showCode);
    }
    
    void loop() {
      gw.process();
    }
    
    void incomingMessage(const MyMessage &message) {
      //char* getString(char *buffer) const;
      // NewRemoteTransmitter transmitter(231337, TRANSMITTER_PIN, 260, 3);
      // address: 231337
      // unit: 0
      // payload: on,off,0-15
      // shutter 11854542 unit 0 on, period: 251us
    
      if (message.type == V_VAR1 ) {
        noInterrupts();
        unsigned long address = getValue(message.data, '/', 0).toInt();
        byte unit = getValue(message.data, '/', 1).toInt();
        String payload = getValue(message.data, '/', 2);
    
        //Serial.println(address);
        //Serial.println(unit);
        //Serial.println(payload);
    
        NewRemoteTransmitter transmitter(address, RF433_TRANSMITTER_DIGITAL_PIN, 260, 5);
        if (payload == "off" || payload == "on" ) {
          transmitter.sendUnit(unit, (payload == "on" ) ? true : false);
        } else {
          transmitter.sendDim(unit, payload.toInt());
        }
    
        // transmitter.sendGroup(false);
    
        interrupts();
      }
    }
    
    // Callback function is called only when a valid code is received.
    void showCode(NewRemoteCode receivedCode) {
      // Note: interrupts are disabled. You can re-enable them if needed.
      combined_received_code = "";
      combined_received_code += receivedCode.address;
    
      combined_received_code += "/";
      if (receivedCode.groupBit) {
        combined_received_code += "group";
      } else {
        combined_received_code += receivedCode.unit;
      }
    
      combined_received_code += "/";
      switch (receivedCode.switchType) {
        case NewRemoteCode::off:
          combined_received_code += "off";
          break;
        case NewRemoteCode::on:
          combined_received_code += "on";
          break;
        case NewRemoteCode::dim:
          combined_received_code += receivedCode.dimLevel;
          break;
        case NewRemoteCode::on_with_dim:
          combined_received_code += receivedCode.dimLevel;
          break;
      }
    
      // Length (with one extra character for the null terminator)
      int str_len = combined_received_code.length() + 1;
    
      // Prepare the character array (the buffer)
      char char_array[str_len];
    
      // Copy it over
      combined_received_code.toCharArray(char_array, str_len);
    
      if (combined_received_code != lastcombined_received_code) {
        gw.send(msgReceive.set(char_array));
        lastcombined_received_code = combined_received_code;
      }
    }
    
    String getValue(String data, char separator, int index) {
      int found = 0;
      int strIndex[] = {
        0, -1
      };
      int maxIndex = data.length() - 1;
    
      for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
          found++;
          strIndex[0] = strIndex[1] + 1;
          strIndex[1] = (i == maxIndex) ? i + 1 : i;
        }
      }
    
      return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
    }
    
    


  • @cdr You've connected both TX and RX module to Arduino?
    The simple chinese ones?

    I can see one potential issue - you have to 'disable' the receiver when transmitter is transmitting, as it might cause interference (interrupt calls on Arduino).



  • The simple Chinese ones yes.

    I have, it seems to work and the code already contains a nointerrupt/interrupt to avoid echo's.


Log in to reply
 

Suggested Topics

  • 3
  • 6
  • 5
  • 2
  • 1

0
Online

11.4k
Users

11.1k
Topics

112.7k
Posts