bit banging between nano every and uno

Dear Folks,

doing very basic one wire bit banging from wall socket nano every to basement relay controller uno. I was using the micro's before and they worked great, but now I got a couple nano every because "she told me 'they are just like the micro's'", turns out, they are not, really

So the very simple protocol goes like this

the nano every listens to a pin and send an 'address' on pin 13 if button is pushed:

if(digitalRead(2) == HIGH){
    //send address 10101010
    digitalWrite(10, HIGH);
    delay(100);
    digitalWrite(10, LOW);
    delay(100);
    digitalWrite(10, HIGH);
    delay(100);
    digitalWrite(10, LOW);
    delay(100);
    ...
}

the uno, in the basement, listens to the wire change and writes the binary character:

if(digitalRead(10) == HIGH) {
    unsigned byte character = 0;
    delay(50);
    bitWrite(character, 1, 7); //1xxxxxxx
    delay(100);
    if(digitalRead(10) == HIGH) {bitWrite(character, 1, 6);} //11xxxxxx
    else{bitWrite(character, 1, 6); //10xxxxxx}
    delay(100);
    if(digitalRead(10) == HIGH) {bitWrite(character, 1, 5);} //1x1xxxxx
    else{bitWrite(character, 1, 5); //1x0xxxxx}
    delay(100);
    if(digitalRead(10) == HIGH) {bitWrite(character, 1, 7);} //1xx1xxxx
    else{bitWrite(character, 1, 7); //1xx0xxxxx}
    delay(100);
    ....
}

but the character the uno reads is correct for the most significant bits, but it looks like lagging in the lsbits.

10000010 becomes 10000001 10000101 becomes 10000010

What is going on here? Is the bitwrite method taking so much overhead on the uno this cannot follow the 100ms delay, or is the nano every just not fit for the job?

PS: I have tried to program the nano every with avrdude directly, but that is even more of a mess ...

Don't use pin 13 for input, it connects already to the LED circuitry.

Sample the input signal between the bits, not at their begin. Add half a bit time after detecting the first bit start.

I guess for: if(digitalRead(13) == HIGH) {bitWrite(character, 1, 6) ;} //11xxxxxx else{bitWrite(character, 1, 6) ; //10xxxxxx}

You mean: if(digitalRead(13) == HIGH) bitWrite(character, 6, 1) ; //11xxxxxx else bitWrite(character, 6, 0) ; //10xxxxxx

If so then the following code is more concise:

 bitWrite(character, 6, digitalRead(pin));

Thank you so much for your replies!!

the #DrDiettrich reply

DrDiettrich: Sample the input signal between the bits, not at their begin. Add half a bit time after detecting the first bit start.

worked perfectly, all is well :)

On with the code, collision detection ...

I am almost there, I can feel it, but there is still something not right.

The wall socket has a nano sending the code when button is pushed like so:

// nano send char

void setup() {
    pinMode(2, INPUT_PULLUP);
    pinMode(10, OUTPUT);
}
void loop() {
    while (1) {
        if (digitalRead(2)==LOW){
            delay(50); // debounce
            if (digitalRead(2)==LOW){
                digitalWrite(, HIGH);  // bit 7 
                delay(100);
                digitalWrite(10, LOW);   // bit 6 
                delay(100);       
                digitalWrite(10, LOW);   // bit 5 
                delay(100);       
                digitalWrite(10, HIGH);   // bit 4 
                delay(100);       
                digitalWrite(10, HIGH);   // bit 3 
                delay(100);       
                digitalWrite(10, HIGH);   // bit 2 
                delay(100);       
                digitalWrite(10, HIGH);   // bit 1 
                delay(100);       
                digitalWrite(10, LOW);   // bit 0
                delay(100);
            }       
        }        
        digitalWrite(10, LOW);    // turn the LED off by making the voltage LOW
    }
}

the wire runs from wall to basement, pulled up with 10kR, into uno listening like so

//UNO LISTEN

void setup() {
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(10, INPUT);
}
void loop() {
    byte character = 0b00000000;
    
    if(digitalRead(10) == HIGH){
        delay(50);
        bitWrite(character, 7, 1);                               // 1xxxxxxx
        delay(100);
        if(digitalRead(10) == HIGH) {bitWrite(character, 6, 1);} // 11xxxxxx
        delay(100);
        if(digitalRead(10) == HIGH) {bitWrite(character, 5, 1);} // 1x1xxxxx
        delay(100);
        if(digitalRead(10) == HIGH) {bitWrite(character, 4, 1);} // 1xx1xxxx
        delay(100);
        if(digitalRead(10) == HIGH) {bitWrite(character, 3, 1);} // 1xxx1xxx
        delay(100);
        if(digitalRead(10) == HIGH) {bitWrite(character, 2, 1);} // 1xxxx1xx
        delay(100);
        if(digitalRead(10) == HIGH) {bitWrite(character, 1, 1);} // 1xxxxx1x
        delay(100);
        if(digitalRead(10) == HIGH) {bitWrite(character, 0, 1);} // 1xxxxxx1
        delay(50);
        if(character == 128){
            digitalWrite(2, HIGH);
            delay(75);
            digitalWrite(2, LOW);
        }
        else if(character == 160){
            digitalWrite(3, HIGH);
            delay(75);
            digitalWrite(3, LOW);
        }
        delay(100);
        character = 0b00000000;
    }
}

but the effect I get is quite cool, if disco effect is what you are looking for. the button has several effects and 80% of the time the correct pin is togled. But what IS going wrong here? i really hope you have the plausible sollution ...

is it really the 10kR pull from the 0V signal wire?

Hmm, dunno what you expect to go on, my crystal ball is in repair.

loop() loops already, no need to insert another while loop.

thanks anyway for your time, let me know when you have your crystal ball back

How can I know what's wrong if you don't say what had been right instead of what you get?

This here 10000010 becomes 10000001 10000101 becomes 10000010 indicates that you should drop the start bit and instead add the last bit. Have a look at the UART data format, with start and stop bits.

Can't you just use SoftwareSerial with a low baud rate. AFAIK 300 is the lowest baud rate supported. Leo..

The mess starts with multiple stations sending at the same time. Collission detection will either kill this project, or the coder will have an IT grade when done ;-)

If you want to write the 3rd bit (bit 2) of character HIGH:

bitWrite(character,2,HIGH);

To write the 8th bit (bit 7) LOW:

bitWrite(character,7,LOW);

The macros from Arduino.h:

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))

DrDiettrich: The mess starts with multiple stations sending at the same time. Collission detection will either kill this project, or the coder will have an IT grade when done ;-)

collision detection is actually not that hard, if you write 0 and read a 1, you stop sending and repeat in 1sec or so

and the idea is to eventually implement a CAN bus with arduino shield, but I want to just get it to work for now

Why not use I2C and the Wire library and shift all the hard word to the microchips?

...R

Or the VirtualWire or RadioHead (in RH_ASK mode) library ? I don't know if they are compatible with the Nano Every. I also don't know how low they can go with the bits per second. If it works, then the communication is reliable.

Multiple senders require special output settings, so that not a high and a low output together cause a short.

still bit banging from wall to basement. as schematics attached showing purple line

All have common ground,
the nano sends one’s and zero’s on the purple wire, depending on button press. These are read by the uno, switching the propper relay. When one nano is connected, all is well, when I hook up a second though, signal is faint and error prone. probably going to be even worse with third and fourth …

So my gut feeling (which is all I have ATM) is to boost the signal going into the uno in the basement.

would the added transistor, resistor and connection in red be a good idea?

Use approved line driver/receiver chips or modules. Current loop or differential transmission provide better results than only amplification. See RS-485 for common transmission devices.

You wrote "So my gut feeling (which is all I have ATM) is to boost the signal going into the uno in the basement. ".

Get rid of your gut feeling. If you don't want to follow the other suggestions, then you need to regenerate the signal by squaring up the transition points on the square wave. Amplifying a distorted signal only makes it more distorted.

Paul

Why did you start a new thread for the same project. Cross-posting is against forum rules.

Did you try 300 baud SoftwareSerial. That should reduce your code to just one command in loop(). For both transmitter and receiver. Leo..