You are reading a single comment by @DrAzzy and its replies. Click here to read the full conversation.
  • Test sending code on Espruino side - this was what I was using for testing different training bursts. Can also just be used to benchmark signal integrity. Sends 32-bit packets - 28 bits data, 4 bits checksum. Bad checksums are rare, but not unheardof.

        var txpin=A1;
    
    function sendCmd(add,cmd,param,ext) {
      ext=ext?ext&15:0;
        var csc=add^cmd^param;
        csc=(csc&15)^(csc>>4)^ext;
        var b=(add<<20)+(cmd<<12)+(param<<4)+ext;
        var d = digitalPulse;
        var p=txpin;
        for (i = 0; i < tp; i++) {
            d(p,1,op); 
            d(p,0,zp); 
        } 
        d(p,1,0.5); //end training burst
        d(p,0,2);
        //send 1s or 0s, and pause
        for (j=27;j>-1;j--) {
            d(p,1,((b>>j)&1)?1.1:0.6); 
            d(p,0,0.65);
        }
        for (j=3;j>-1;j--) {
            d(p,1,((csc>>j)&1)?1.1:0.6); 
            d(p,0,0.65);
        }
        // wait for finish
        d(p,0,0);
      digitalWrite(p,0);
    }
    
    function testRun(train,opp,zpp,number,interval) {
      tp=train;
      op=opp;
      zp=zpp;
      var ad=Math.round(255*Math.random());
      var pr=Math.round(255*Math.random());
      var cm=Math.round(198*Math.random());
      var ex=Math.round(16*Math.random());
      inter=setInterval("sendCmd(ad,cm,pr,ex);ad=pr=Math.round(255*Math.random());cm=Math.round(198*Math.random());ex=Math.round(16*Math.random());",interval);
      setTimeout("clearInterval(inter);",number*interval);
      setTimeout("sendCmd(31,200,150,10);console.log('done')",(number+5)*interval);
    }
    
    

    Test receiving code on Arduino side:

    
    [#define](https://forum.espruino.com/search/?q=%23define) rxpin 19
    
    int lastPinState;
    unsigned long lastPinHighTime;
    unsigned long lastPinLowTime;;
    unsigned long lastTempHighTime=0;
    unsigned long lastTempLowTime=0;
    unsigned long rxdata;
    int lastTempPinState;
    int bitsrx;
    int rxing;
    int MyState;
    unsigned long curTime;
    int count=0;
    int badcsc=0;
    
    
    void setup() {
            lastPinState=0;
            lastPinLowTime=0;
            lastPinHighTime=0;
            rxdata=0;
            bitsrx=0;
            rxing=0;
            MyState=2;
    	Serial.begin(9600);
    }
    
    void loop() {
            curTime=micros();
    	onListenST();
    }
    
    void onListenST() {
    	int 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;
    				//Serial.print("F");
                    //Serial.println(bitlength);
    			} else if (bitlength > 1000 && bitlength < 1150 ) {
    				rxdata=(rxdata<<1)+1;
    				//Serial.print("T");
                                    //Serial.println(bitlength);
    			} else {
    				resetListen();
    				return;
    			}
    			bitsrx++;
    			if (bitsrx==32) {
    				Serial.print("Got 32 bits ");
    				Serial.print((rxdata>>24)&0xFF);
    				Serial.print(":");
    				Serial.print((rxdata>>16)&0xFF);
    				Serial.print(":");
    				Serial.print((rxdata>>8)&0xFF);
    				Serial.print(":");
    				Serial.println((rxdata)&0xFF);
    				Serial.println(rxdata);
    				parseRx(rxdata);
    				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;
    }
    void parseRx(unsigned long rxd) {
    	Serial.println("Parsing: ");
    	unsigned char rcvB0=(rxd>>24)&0xFF;
    	unsigned char rcvCmd=(rxd>>16)&0xFF;
    	unsigned char rcvParam=(rxd>>8)&0xFF;
    	unsigned char rcvB3=(rxd)&0xFF;
    	unsigned char rcvAdd=rcvB0&0x3F;
    	unsigned char rcvExtParam=(rcvB3>>4);
    	unsigned char calccsc=(rcvB0^rcvCmd^rcvParam);
    	calccsc=(calccsc&15)^(calccsc>>4)^rcvExtParam;
    	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++;
          	        }
    		Serial.println("Valid transmission received!");
    	} else {
            Serial.print(calccsc);
    		Serial.println("No good!");
            badcsc++; 
    	}
    }
    
    

    I settled on a 20ms training burst with 0.4ms up 0.4ms down. Bit lengths were adjusted a bit from earlier to better balance the duty cycle, which might become more relevant if i was sending longer packets. I decided to structure the command as:

    2 bits (reserved)
    6 bits (device address)
    8 bits (command)
    8 bits (params)
    4 bits (extended params)
    4 bits (checksum)

    
    var txpin=A1;
    
    
    function sendCmd(add,cmd,param,ext) {
      ext=ext?ext&15:0;
        var csc=add^cmd^param;
        csc=(csc&15)^(csc>>4)^ext;
        var b=(add<<20)+(cmd<<12)+(param<<4)+ext;
        var d = digitalPulse;
        var p=txpin;
        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);
        //send 1s or 0s, and pause
        for (j=27;j>-1;j--) {
            d(p,1,((b>>j)&1)?1.1:0.6); 
            d(p,0,0.65);
        }
        for (j=3;j>-1;j--) {
            d(p,1,((csc>>j)&1)?1.1:0.6); 
            d(p,0,0.65);
        }
        // wait for finish
        d(p,0,0);
      digitalWrite(p,0);
    }
    
    

    And the parserx will be:

    
    void parseRx(unsigned long rxd) {
    	Serial.println("Parsing: ");
    	unsigned char rcvB0=(rxd>>24)&0xFF;
    	unsigned char rcvCmd=(rxd>>16)&0xFF;
    	unsigned char rcvParam=(rxd>>8)&0xFF;
    	unsigned char rcvB3=(rxd)&0xFF;
    	unsigned char rcvAdd=rcvB0&0x3F;
    	unsigned char rcvExtParam=(rcvB3>>4);
    	unsigned char calccsc=(rcvB0^rcvCmd^rcvParam);
    	calccsc=(calccsc&15)^(calccsc>>4)^rcvExtParam;
    	rcvB3=rcvB3&15;
    	if (calccsc==rcvB3) {
    		if (rcvAdd==MyAddress) {
    			Serial.println("Valid transmission received!");
    			//Handle the command
    		} else {
    			Serial.println("Wrong address - not for me");
    		}
    	} else {
                    Serial.print(calccsc);
    		Serial.println("No good!");
                    badcsc++; 
    	}
    }
    
    

    Also - what a difference an antenna makes. Just poking a dupont male jumper into that hole (no solder or anything) and letting it dangle has a huge effect on packet loss...

About

Avatar for DrAzzy @DrAzzy started