Serial.write and Serial.read Xbee also port manipulation

Ive been stuck on some code for about two days it should be simple but i cant seem to find what i need.

I need to read the state of 8 digital pins on UNO1 send it over xbee1 as 1 byte, to xbee2 on UNO2, read it and set 8 digital output pins.
Should be easy right??

Here is the structure Im looking for.

UNO1 read PORTB and PORTC
Use last four pins of PORTB and first four pins of PORTC to make 1 byte representing the status of the 8 input pins 10-17.
Send over serial as 1 byte.
Capture on UNO2 and map back to PORTB and PORTC, set output of pins 10-17 to match.

Ive tried a few things with the serial monitor and cannot seem to send in binary or receive in binary which is where I think I should start. I have read up on port manipulation and think I can come up with something for that, also splitting and adding to bytes.

Should be easy right??

Yes, it should (and is).

UNO1 read PORTB and PORTC

As opposed to digitalRead() for readability?

Use last four pins of PORTB and first four pins of PORTC to make 1 byte representing the status of the 8 input pins 10-17.

OK. You can do that.

Send over serial as 1 byte.

You can do that, too.

Capture on UNO2 and map back to PORTB and PORTC, set output of pins 10-17 to match.

Possible, yes.

Ive tried a few things with the serial monitor and cannot seem to send in binary or receive in binary which is where I think I should start.

Serial.write() sends in binary. Serial.read() doesn't know binary from Tuesday.

I have read up on port manipulation and think I can come up with something for that, also splitting and adding to bytes.

Well good.

Did you have a question?

To start with Ive been using just a UNO and serial monitor to test serial.write and serial.read functions. I don't think serial monitor acts like i was thinking it would so that is the reason Im not getting the expected results...??? Is there a better interface to use for testing those functions. Or will i need to wire up the Xbees and UNOs in a working environment to test?

As for reading the PORTS directly i was hoping it would be easier and also speed things up "use less clock cycles". I think this code should end up being fairly short. I guess I could use digital.read, add each state to a string, convert to a byte, then send it.

To start with Ive been using just a UNO and serial monitor to test serial.write and serial.read functions.

Sending binary data to the Serial Monitor is not terribly effective.

The Serial Monitor can not send binary data.

Or will i need to wire up the Xbees and UNOs in a working environment to test?

I don't see any other way.

As for reading the PORTS directly i was hoping it would be easier and also speed things up "use less clock cycles".

It would.

I guess I could use digital.read, add each state to a string

Why would you want to convert to a string and back? Just use bitWrite() to set the bit in the byte.

Didn't think of bitWrite, and it is what I was trying to accomplish. Here is what I put together for the loop input code.

void loop (){
if (digitalRead(row1) == HIGH){bitWrite(bytetosend, 0, 1);} else {bitWrite(bytetosend, 0, 0);}
if (digitalRead(row2) == HIGH){bitWrite(bytetosend, 1, 1);} else {bitWrite(bytetosend, 1, 0);}
if (digitalRead(row3) == HIGH){bitWrite(bytetosend, 2, 1);} else {bitWrite(bytetosend, 2, 0);}
if (digitalRead(row4) == HIGH){bitWrite(bytetosend, 3, 1);} else {bitWrite(bytetosend, 3, 0);}
if (digitalRead(row5) == HIGH){bitWrite(bytetosend, 4, 1);} else {bitWrite(bytetosend, 4, 0);}
if (digitalRead(row6) == HIGH){bitWrite(bytetosend, 5, 1);} else {bitWrite(bytetosend, 5, 0);}
if (digitalRead(row7) == HIGH){bitWrite(bytetosend, 6, 1);} else {bitWrite(bytetosend, 6, 0);}
if (digitalRead(row8) == HIGH){bitWrite(bytetosend, 7, 1);} else {bitWrite(bytetosend, 7, 0);}

Serial.write(bytetosend);
delay(50);
}

Updates approximately a little less than 20hz. And isn't very much code. Look ok??

Even shorter:

void loop ()
{
  bitWrite(bytetosend, 0, digitalRead(row1));
  bitWrite(bytetosend, 1, digitalRead(row2));
  bitWrite(bytetosend, 2, digitalRead(row3));
  bitWrite(bytetosend, 3, digitalRead(row4));
  bitWrite(bytetosend, 4, digitalRead(row5));
  bitWrite(bytetosend, 5, digitalRead(row6));
  bitWrite(bytetosend, 6, digitalRead(row7));
  bitWrite(bytetosend, 7, digitalRead(row8));

  Serial.write(bytetosend);
  delay(50);
}

And if you put the pin numbers in an array it could be reduced even further.

Nice, that will be much easier than port manipulation. To make it shorter, this code compiles i think it should work....??? I'm using pins 2-9

void loop ()
{  
  for (int Bit = 0; Bit < 8; Bit++) {
    bitWrite(bytetosend, Bit, digitalRead(Bit+2));
  }    
  Serial.write(bytetosend); 
  delay(50);
}

To make it shorter, this code compiles i think it should work....??? I'm using pins 2-9

If you won't ever change pins (and you put that { on the next line where it belongs), then, yes.

Great much better than I had planned. The pins wont all change their state at the same time but it shouldn't make a difference on my project. And this code for the Output on UNO2 pins 2-9.???

void loop ()
{
  
if (Serial.available()) 
{
  byte incomingByte = Serial.read();
  
    for (int Bit = 0; Bit < 8; Bit++) 
    {
      digitalWrite(Bit+2, bitRead(incomingByte, Bit));
    }
}
delay(10);
}

The pins wont all change their state at the same time but it shouldn't make a difference on my project.

They will change pretty close together.

And this code for the Output on UNO2 pins 2-9.???

Looks good.

Paul,

Thanks for the push in the right direction. Here is how the complete output code turned out. Very slim and compact(i think anyway). Hope the thread can help others too.

void setup()
{
Serial.begin(9600);

for (int Pin = 2; Pin < 10; Pin++) 
  {
  pinMode(Pin, OUTPUT);
  }
}

void loop ()
{
  
if (Serial.available()) 
  {
    byte incomingByte = Serial.read();
  
      for (int Bit = 0; Bit < 8; Bit++) 
      {
        digitalWrite(Bit+2, bitRead(incomingByte, Bit));
      }
  }
delay(10);
}

I'm questioning if the below code is the way to do this. I need to now send data both ways. So both are sending data every 50ms and checking for data every 1ms (as long as it didn't have to send in the loop before). That way they should never fall behind. Since the data being received, doesn't effect what is being sent, it doesn't need to be synced. Look correct?

INPUTS

void loop ()
{
  if (Serial.available()) 
  {
    byte incomingByte = Serial.read(); // Read byte 
    digitalWrite(11, bitRead(incomingByte, 0)); // Turn on/off pin 11 via 0 bit of the sent byte
  }
  
  if( (long)( millis() - sendMillis ) >= 0) // If next send time, check pins and send
  {
    for (int Bit = 0; Bit < 8; Bit++) {bitWrite(bytetosend, Bit, digitalRead(Bit+2));} // Read pins 2-10 and set all 8 bits of byte to send.   
    Serial.write(bytetosend); // Send byte
    sendMillis += 50;  // Set next send time
  }
delay(1); // NOT SURE TO USE THIS LINE OR NOT 
}

OUTPUTS

void loop ()
{
  
  if (Serial.available()) 
  {
    byte incomingByte = Serial.read();
    for (int Bit = 0; Bit < 8; Bit++){digitalWrite(Bit+2, bitRead(incomingByte, Bit));}
  }
    
  if( (long)( millis() - sendMillis ) >= 0) // If next send time, check pins and send
  {
    bitWrite(bytetosend, 0, digitalRead(11)); // Read pin 11 and set 0 bit of byte to send.   
    Serial.write(bytetosend); // Send byte
    sendMillis += 50;  // Set next send time
  }
delay(1); // NOT SURE
}

Neither Arduino should delay() at the end of loop. You don't want to "check for data every 1ms". You want to discover that there is data to read as soon as possible after it arrives.

Keeping track of the next time to send by adding to the send time is wrong. You keep track of the last time data was send, and see if it is time to send again by subtraction. That is guaranteed to work across rollover. Your way will not.

If sendMillis is of the write type (unsigned long), the cast is not needed. If it is not, the cast is useless. In either case, you can get rid of it.

Please. Put each { and each } and each statement on a new line. Reading code down the page is far easier than reading code across the page. It also makes the { and } stand out better.

The sendMillis is based on this link in the arduino playground. Arduino Playground - TimingRollover Did I understand it wrong? I probably should have post my entire code.?.?

The delay was based on a lot of forum post, without it people had some problems with serial.available function. If its not needed I will gladly take it out.

My code is still formatted the way you asked, for the post i "grouped" the code that we have discussed already to kind of "ignore" it. I will leave it alone in any new post.

Thanks Again.

Did I understand it wrong?

No. It's just not the best way to use millis().

unsigned long lastTime = 0;
unsigned long thisTime;
unsigned long interval = 50;

void loop()
{
  thisTime = millis();
  if(thisTime - lastTime >= interval)
  {
    // It's time to do something

    lastTime = thisTime;
  }
}

is the preferred way of using millis() to cause things to happen based on when the event last happened.

I finally understand how that will work with a "rollover"! I looked back at some old projects and Ive used it before but never understood why it works.

Unsigned will rollover backwards instead of negatively. So lets say the rollover is 600 just to make it easy...

unsigned int last = 595;
unsigned int current = 25;
current - last = 30 not -570!!

so 5 past before rollover(at 600) and 25 since rollover = 30 total. Because of the way unsigned works. 25-595 gets to zero at 570 so then count backwards from rollover(600) or (600-570) and get 30.

Hope that mess above can help others understand how they work.

This is the code I used.

if(millis() - previousMillis ) >= interval)                     // If time to send
{
   bitWrite(bytetosend, 0, digitalRead(11));              // Read pin 11 and set 0 bit of byte to send.   
   Serial.write(bytetosend);                                     // Send byte
   previousMillis = millis();                                       // Set sent time
}

Unsigned will rollover backwards instead of negatively.

An unsigned variable does not go negative when rollover occurs. It doesn't go backwards, either, though. It simply starts over again at 0, like a car odometer.

One has no trouble determining how far they have traveled if the starting mileage is 99,790 miles and the ending mileage is 420. The computer has no trouble, either.