433mhz Espruino <-> Arduino

Posted on
Page
of 2
Prev
/ 2
  • Yep - especially where seconds/milliseconds are concerned, pretty much everything can be fractional.

  • Debounce of 0.35 helps, but still usually gets FIFO_FULL. Going higher than that causes it to fail to recognize messages, which is strange, seeing as the message pulses should be 0.6ms long. I have a few ideas to try tomorrow.

    However, during the transmissions and receiving, it performs beautifully! I've successfully received transmissions up to 30 bytes long so far (240 bits!), and expect to be able to go higher so while it's receiving, its clearly handling the input just fine.

  • Wow, that really is good! Thanks for the update...

    This should make a really cool module :)

  • But i'd be interested to see what's up with debounce - it could be an implementation issue I guess...

  • changed sigOff() a bit, so it should still count it, even if the next bit of noise looks like a bit.

    
    function sigOff(e) {
      var d=e.time-e.lastTime;
      if (d>0.0005 && d<0.0013) n+=d>0.0008?1:0;
      else{
        n="";
      }
      if (n.length==z)  parseRx(n);
    }
    
    

    z is global variable with the bit size of the packet being received.

    
    >runTest4(32,5,0);
    =undefined
    Listening started
    0110010001100101011001100110011101101000­0110100101101010011010110110110001101101­0110111001101111011100000111000101110010­0111001101110100011101010111011001110111­0111100001111001011110100111101101111100­0111110101111110011111111000000010000001­1000001010000011
    B0:100 B1:101 B2:102 B3:103 B4: 104 B5: 105 B6: 106 B7: 107
    B8:108 B9:109 B10:110 B11:111 B12: 112 B13: 113 B14: 114 B15: 115
    B16:116 B17:117 B18:118 B19:119 B20: 120 B21: 121 B22: 122 B23: 123
    B24:124 B25:125 B26:126 B27:127 B28: 128 B29: 129 B30: 130 B31: 131
    
    
    
    Starting transmit
    32 byte payloadTransmit 3 called...
    B0: 100
    B1: 101
    B2: 102
    B3: 103
    B4: 104
    B5: 105
    B6: 106
    B7: 107
    B8: 108
    B9: 109
    B10: 110
    B11: 111
    B12: 112
    B13: 113
    B14: 114
    B15: 115
    B16: 116
    B17: 117
    B18: 118
    B19: 119
    B20: 120
    B21: 121
    B22: 122
    B23: 123
    B24: 124
    B25: 125
    B26: 126
    B27: 127
    B28: 128
    B29: 129
    B30: 130
    B31: 131
    Payload generated.
    Sending round 0
    Sending round 1
    Sending round 2
    Sending round 3
    Sending round 4
    Transmit done
    
    
    
    sendRaw([0xC0,100,101,102,103,104,105,10­6,107,108,109,110,111,112,113,114,115,11­6,117,118,119,120,121,122,123,124,125,12­6,127,128,129,130],5);
    
    

    (first byte is being used as a signal as to what the size of the transmission is)

    
    256
    Receive done
    Parsing long packet
    192
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    Done
    
    

    Test code:

    
    var txpin=C7;
    var rxpin = C6;
    var n="";
    var wf;
    
    var z=32; //This is the length of packet to receive, in bits. 
    
    function sendRaw(dat,rep) {
      rep=rep?rep:5;
      var l=dat.length;
        var d = digitalPulse;
        var p=txpin;
        var h;
      for (var v=0;v<rep;v++) {
        for (i = 0; i < 25; i++) {
              d(p,1,0.4); 
              d(p,0,0.4); 
          }
          d(p,1,0.5); //end training burst
          d(p,0,2);
          for (var j=0;j<l;j++) {
            h=dat[j];
            for (k=7;k>=0;k--) {
            d(p,1,((h>>k)&1)?1.1:0.6); 
            d(p,0,0.65);
            }
          }
            d(p,0,0);
      }
        digitalWrite(txpin,0);
    }
    
    function sigOff(e) {
      var d=e.time-e.lastTime;
      if (d>0.0005 && d<0.0013) n+=d>0.0008?1:0;
      else{
        n="";
      }
      if (n.length==z)  parseRx(n);
    }
    
    function parseRx(rcv) {
      
      console.log(rcv);
      stopListen();
      var b3=parseInt(rcv.substr(24,8),2);
      var b2=parseInt(rcv.substr(16,8),2);
      var b1=parseInt(rcv.substr(8,8),2);
      var b0=parseInt(rcv.substr(0,8),2);
      var b4=parseInt(rcv.substr(32,8),2);
      var b5=parseInt(rcv.substr(40,8),2);
      var b6=parseInt(rcv.substr(48,8),2);
      var b7=parseInt(rcv.substr(56,8),2);
      var b8=parseInt(rcv.substr(64,8),2);
      var b9=parseInt(rcv.substr(72,8),2);
      var b10=parseInt(rcv.substr(80,8),2);
      var b11=parseInt(rcv.substr(88,8),2);
      var b12=parseInt(rcv.substr(96,8),2);
      var b13=parseInt(rcv.substr(104,8),2);
      var b14=parseInt(rcv.substr(112,8),2);
      var b15=parseInt(rcv.substr(120,8),2);
      var b16=parseInt(rcv.substr(128,8),2);
      var b17=parseInt(rcv.substr(136,8),2);
      var b18=parseInt(rcv.substr(144,8),2);
      var b19=parseInt(rcv.substr(152,8),2);
      var b20=parseInt(rcv.substr(160,8),2);
      var b21=parseInt(rcv.substr(168,8),2);
      var b22=parseInt(rcv.substr(176,8),2);
      var b23=parseInt(rcv.substr(184,8),2);
      var b24=parseInt(rcv.substr(192,8),2);
      var b25=parseInt(rcv.substr(200,8),2);
      var b26=parseInt(rcv.substr(208,8),2);
      var b27=parseInt(rcv.substr(216,8),2);
      var b28=parseInt(rcv.substr(224,8),2);
      var b29=parseInt(rcv.substr(232,8),2);
      var b30=parseInt(rcv.substr(240,8),2);
      var b31=parseInt(rcv.substr(248,8),2);
      console.log("B0:"+b0+" B1:"+b1+" B2:"+b2+" B3:"+b3+" B4: "+b4+" B5: "+b5+" B6: "+b6+" B7: "+b7);
      console.log("B8:"+b8+" B9:"+b9+" B10:"+b10+" B11:"+b11+" B12: "+b12+" B13: "+b13+" B14: "+b14+" B15: "+b15);
      console.log("B16:"+b16+" B17:"+b17+" B18:"+b18+" B19:"+b19+" B20: "+b20+" B21: "+b21+" B22: "+b22+" B23: "+b23);
      console.log("B24:"+b24+" B25:"+b25+" B26:"+b26+" B27:"+b27+" B28: "+b28+" B29: "+b29+" B30: "+b30+" B31: "+b31);
    }
    
    function startListen() {
      wf=setWatch(sigOff,C6,{repeat:true,debou­nce:0.35,edge:"falling"});
      console.log("Listening started");
    }
    function stopListen() {
      if (wf) {clearWatch(wf);}
      wf=0;
      n="";
    }
    
    
    function runTest(add,inc) {
        z=32;
        var csc=31^0xF2^add;
        csc=(csc&15)^(csc>>4)^inc;
        sendRaw([31,0xF2,add,((inc<<4)+csc)],5);­
        setTimeout("startListen()",400);
        setTimeout("stopListen()",2500);
    }
    
    
    function runTest4(datalength,replyrepeat,sub) {
        z=datalength*8-sub;
        var csc=31^0xF4^datalength;
        csc=(csc&15)^(csc>>4)^replyrepeat;
        sendRaw([31,0xF4,datalength,((replyrepea­t<<4)+csc)],5);
        setTimeout("startListen()",400);
        setTimeout("stopListen()",2500);
    }
    
    
    function sendLong4() {
        sendRaw([0x40,100,101,102],5);
    }
    
    function sendLong8() {
        sendRaw([0x40,100,101,102,103,104,105,10­6],5);
    }
    
    function sendLong16() {
        sendRaw([0x80,100,101,102,103,104,105,10­6,107,108,109,110,111,112,113,114],5);
    }
    
    function sendLong32() {
        sendRaw([0xC0,100,101,102,103,104,105,10­6,107,108,109,110,111,112,113,114,115,11­6,117,118,119,120,121,122,123,124,125,12­6,127,128,129,130],5);
    }
    
    
    

    And on the Arduino:

    
    [#define](http://forum.espruino.com/sear­ch/?q=%23define) ListenST 1
    [#define](http://forum.espruino.com/sear­ch/?q=%23define) CommandST 2
    [#define](http://forum.espruino.com/sear­ch/?q=%23define) TransmitST 3
    [#include](http://forum.espruino.com/sea­rch/?q=%23include) <EEPROM.h>
    
    [#define](http://forum.espruino.com/sear­ch/?q=%23define) rxpin 19
    [#define](http://forum.espruino.com/sear­ch/?q=%23define) txpin 18
    
    
    unsigned char MyAddress=31;
    byte lastPinState;
    unsigned long lastPinHighTime;
    unsigned long lastPinLowTime;;
    unsigned long lastTempHighTime=0;
    unsigned long lastTempLowTime=0;
    unsigned char rxdata;
    byte lastTempPinState;
    int bitsrx;
    int rxing;
    int MyState;
    unsigned char MyCmd;
    unsigned char MyParam;
    unsigned char MyExtParam;
    unsigned long curTime;
    int count=0;
    int badcsc=0;
    int pksize=32;
    char rxaridx;
    unsigned char txrxbuffer[32];
    byte TXLength;
    
    void setup() {
            lastPinState=0;
            lastPinLowTime=0;
            lastPinHighTime=0;
            rxdata=0;
            bitsrx=0;
            rxing=0;
            MyState=2;
    	Serial.begin(9600);
    }
    
    void loop() {
            curTime=micros();
    	if (MyState==ListenST) {
    		onListenST();
    	} else if (MyState==CommandST){ 
    		onCommandST();
    	} else {
    		MyState=ListenST; //in case we get into a bad state somehow.
    	}
    }
    
    void onCommandST() {
    	if (MyCmd==0xF2) {
    		Serial.println("Starting transmit info");
    		prepareEEPReadPayload();
    		delay(500);
    		doTransmit(5);
                    ClearCMD();
                    MyState=1;
    	} else if (MyCmd==0xF4) {
    		Serial.println("Starting transmit");
                    Serial.print(MyParam);
                    Serial.print(" byte payload");
    		prepareTestPayload();
                    delay(500);
                    doTransmit(MyExtParam);
                    ClearCMD();
                    MyState=1;
    	} else {
    		Serial.println("Invalid command type");
    		ClearCMD();
    		MyState=1;
    	}
    }
    
    
    void prepareEEPReadPayload() {
            unsigned char Payload1=EEPROM.read(MyParam);
    	unsigned char Payload2=EEPROM.read(MyParam+MyExtParam)­;
    	unsigned char oldcsc=((MyAddress&0xF0)>>4)^(MyAddress&­0x0F)^(0x0F)^(0x02)^((MyParam&0xF0)>>4)^­(MyParam&0x0F)^(MyExtParam&0x0F);
    	txrxbuffer[0]=MyAddress;
    	txrxbuffer[1]=EEPROM.read(MyParam);
    	txrxbuffer[2]=EEPROM.read(MyParam+MyExtP­aram);
    	unsigned char csc=((MyAddress&0xF0)>>4)^(MyAddress&0x0­F)^((MyCmd&0xF0)>>4)^(MyCmd&0x0F)^((MyPa­ram&0xF0)>>4)^(MyParam&0x0F)^(oldcsc&0x0­F);
    	txrxbuffer[3]=oldcsc<<4+(csc&0x0F);
            TXLength=4;
    }
    
    void prepareTestPayload() {
    	Serial.println("prepareTestPayload called...");
    	for (byte i=0;i<MyParam;i++) {
    		txrxbuffer[i]=100+i;
    		Serial.print("B");
    		Serial.print(i);
    		Serial.print(": ");
    		Serial.println(txrxbuffer[i]);
    	}
    	Serial.println("Payload generated.");
    	TXLength=MyParam;
    }
    
    void doTransmit(int rep) {
    	for (byte r=0;r<rep;r++) {
    		//now we start sending;
    		//Serial.print("Sending round ");
    		//Serial.println(r);
    		//delay(10);
    		for (byte j=0; j < 30; j++) {
    			delayMicroseconds(400);
    			digitalWrite(txpin, 1);
    			delayMicroseconds(400);
    			digitalWrite(txpin, 0);
    		}
    		delayMicroseconds(2000);
    		for (byte k=0;k<TXLength;k++) {
    			//send a byte
    			for (int m=7;m>=0;m--) {
    				digitalWrite(txpin, 1);
    				if ((txrxbuffer[k]>>m)&1) {
    					delayMicroseconds(1100);
    				} else {
    					delayMicroseconds(600);
    				}
    				digitalWrite(txpin, 0);
    				delayMicroseconds(650);
    			}
    			//done with that byte
    		}
    		//done with sending this packet;
    		digitalWrite(txpin, 0); //make sure it's off;
    		delayMicroseconds(2000); //wait 2ms before doing the next round. 
    	}
    	Serial.println("Transmit done");
    	TXLength=0;
    }
    
    
    
    void ClearCMD() {
    	MyParam=0;
    	MyExtParam=0;
    	MyCmd=0;
    }
    
    
    void onListenST() {
    	byte pinState=digitalRead(rxpin);
            if (pinState==lastPinState) {
    		return;
    	} else {
                  lastPinState=pinState;
            }
    	if (pinState==0) {
    		lastPinLowTime=curTime;
    		unsigned long bitlength=lastPinLowTime-lastPinHighTime­;
    		if (bitlength > 1500) {
    			resetListen();
    			return;
    		} else if (rxing==1) {
    			if (bitlength > 475 && bitlength < 650) {
    				rxdata=rxdata<<1;
    			} else if (bitlength > 1000 && bitlength < 1150 ) {
    				rxdata=(rxdata<<1)+1;
    			} else {
    				resetListen();
    				return;
    			}
    			bitsrx++;
    			if (bitsrx==2) {
    				pksize=32<<rxdata;
    			} else if (bitsrx==8*(1+rxaridx)) {
    				txrxbuffer[rxaridx]=rxdata;
    				rxdata=0;
    				rxaridx++;
    				if (rxaridx*8==pksize) {
    					Serial.println(bitsrx);
    					Serial.println("Receive done");
    					Serial.println(pksize);
    					if (pksize==32) {
      						parseRx(txrxbuffer[0],txrxbuffer[1],txrx­buffer[2],txrxbuffer[3]);
      					}
    					parseRx2(txrxbuffer,pksize/8);
    					resetListen();
    				}
    			}
    			return;
    		}   
    	} else {
    		lastPinHighTime=curTime;
                    if (lastPinHighTime-lastPinLowTime > 1900 && lastPinHighTime-lastPinLowTime <2100 && rxing==0) {
                      rxing=1;
                      return;
                    }
    		if (lastPinHighTime-lastPinLowTime > 800 && rxing==1) {
                Serial.println(bitsrx);
    			resetListen();
    			return;
    		}
    	}
    }
    
    
    void resetListen() {
            //Serial.print("end");
    	bitsrx=0;
    	rxdata=0;
        rxing=0;
        rxaridx=0;
    }
    
    //Just for test/debug purposes;
    void parseRx2(unsigned char rxd[],byte len) {
      
    	Serial.println("Parsing long packet");
    	for (byte i=0;i<len;i++) {
    		Serial.println(rxd[i]);
    	}
    	Serial.println("Done");
    }
    
    void parseRx(unsigned char rcvB0,unsigned char rcvCmd,unsigned char rcvParam,unsigned char rcvB3) {
    	Serial.println("Parsing: ");
    	unsigned char rcvAdd=rcvB0&0x3F;
    	unsigned char rcvExtParam=(rcvB3>>4);
    	unsigned char calccsc=(rcvB0^rcvCmd^rcvParam);
    	calccsc=(calccsc&15)^(calccsc>>4)^rcvExt­Param;
    	rcvB3=rcvB3&15;
    	
    	if (calccsc==rcvB3) {
                    if (rcvCmd==200) {
          		    	Serial.print(count);
          		    	Serial.println(" received.");
          		    	count=0;
          		    	Serial.print(badcsc);
          		    	Serial.println(" .");
          		    	badcsc=0;
          	        } else {
          	        	count++;
    			MyCmd=rcvCmd;
    			MyParam=rcvParam;
    			MyExtParam=rcvExtParam;
    			MyState=CommandST;
          		    	Serial.println(rcvCmd);
          		    	Serial.println(rcvParam);
          		    	Serial.println(rcvExtParam);
          		    	Serial.println(MyState);
    
          	        }
    		Serial.println("Valid transmission received!");
    	} else {
            Serial.print(calccsc);
    		Serial.println("No good!");
            badcsc++; 
    	}
    }
    
    

    As you can see, the Arduino code could still use some tidying.

    The arduino side needs some serious tidying - I'd like to turn both sides into a generic skeleton that can just send and receive data.

    Edit: Did a lot of that tidying. I need to put some thought into how I name variables, in general, because pulling them out of my ass as I need them like I've (obviously) been doing doesn't produce pleasing nor easy to maintain code. I also need to find a graceful solution to tabs vs spaces. I prefer tabs, but arduino IDE does 2 spaces.

    And from there, extend my parsing to work on 8/16/32 byte packets, doing checksum, device address checking, etc, and then I can get down to making something with it.

  • On the JS side, you could do something like:

    var names = ["foo","bar","..."];
    var obj = {}
    names.forEach(function(n,i) { obj[n] = parseInt(rcv.substr(8*i,8),2); });
    

    could be a really neat tidy way of making an object with your data?

  • Don't know if this is handy or not, but I have some really simple code online that will decode 433Mhz signals and then send the results up to Xively: http://forum.espruino.com/conversations/­258645/#comment11985738

    Could be pretty handy for doing cheap wireless sensors.

  • Finally got my 433s to not sit around anymore... but for a different project I'm looking into. A real project in the field - literally: sensors in fields around a agriculture utility building/ installation. The sensors are up to 500 feet away from a central node sitting on top of the utility building.

    First thing is to get some hands-on with the wireless communication - in two parts:

    1. suitable antennas: 1/4 L ground planes for the transmitters and Slim Jim / J-pole for the receiver. None of them are directional. I may end up with directional ones for the transmitters.
    2. Explore software options to validate distance - first within 10s of feet - using simple (tuned) wire antennas.

    Latter was so far doomed... I used the 433 Espruino modules but I got nothing across... with vaious pairs (3)... so I looked into what the receiver actually puts out... and from some base analysis I may get a few bps going... like: blink - on/off - the transmitter and see the same LED on/off pattern on the receiver side. I used 2 PICOS, transmitter on 5V USB for one models, 3.3V on the other models. With first model I could go up to 12V.

    The disheartening experience already over short distance made me quickly forget the 433 ASK/OOK modulation and go for something real, like LoRa... Sure, I could pour over the various code options and use dedicated hardware on the receiver side... may be that I should be glad for the early failure...

    Now I'm waiting for the arrival of the new hardware. The ground plane antennas I can reuse. They need just retrimning: cutting the wip and radials to the new, higher frequency. Same for the J-pole and adjusting its feed point.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

433mhz Espruino <-> Arduino

Posted by Avatar for DrAzzy @DrAzzy

Actions