Pages: 1 [2]   Go Down
Author Topic: Reading Continuous Serial Packets  (Read 1462 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

New Master Code

#include <Wire.h>

// BFF Binary actuator code sequence

int A; // First Start of data identifier
int B; // Second Start data identifier
int C; // Reserved
int Act1;
int Act2;
int Act3;
int Act4;
int Act5;
int Act6;


int j1;
int j2;

void setup()
{
   
  Serial.begin(9600); 
  Serial.flush();
  Wire.begin(); // join i2c bus (address optional for master)
}

void loop() {
  // read the oldest byte in the serial buffer:
   
   if (Serial.available() > 0) {
    j1 = Serial.read();
 
    if (j1 == 'A'){     // Find the first indentifing char
             
              if (Serial.available() > 0)
              //delay (11); // It seems to need a delay here
              B = char (Serial.read()); // read second start identifier
             
              if (Serial.available() > 0)
              //delay (20);
              //Serial.print(B);
              C = char(Serial.read());  // read reseved identifer
             
              if (Serial.available() > 0)
             
              //delay (20);
              //Serial.print(C);
              Act1 = int(Serial.read()); // read actuator 1
             
              if (Serial.available() > 0)
             
              //delay (20);
              //Serial.print(Act1);
              Act2 = int(Serial.read()); // read actuator 2
             
              if (Serial.available() > 0)
              //delay (20);
              //Serial.print(Act2);
              Act3 = int(Serial.read()); // read actuator 3
             
              if (Serial.available() > 0)
              //delay (20);
              //Serial.print(Act3);
              Act4 = int(Serial.read()); // read actuator 4
             
              if (Serial.available() > 0)
              //delay (20);
              //Serial.print(Act4);
              Act5 = int(Serial.read()); // read actuator 5
             
             if (Serial.available() > 0)
             // delay (20);
              //Serial.print(Act5);
              Act6 = int(Serial.read()); // read actuactor 6)
              //Serial.print(Act6);
         
          delay (100);
         
   
   
    Wire.beginTransmission(1); // transmit to device #4
    Wire.write("Ac1= ");        // sends five bytes         
    Wire.write(Act1);              // sends one byte           
    Wire.endTransmission();    // stop transmitting         
    delay(100);         
             
           

}

}
   


Slave code was changed where if goto's were commented out Stream continue to show out-liars.

Thanks for the learning experience.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 237
Posts: 24276
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

And what If Serial.available isn't greater than zero?
What about some CODE TAGS?
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is another piece of Master code to test throughput

Master

 #include <Wire.h>
 
  void setup() { 
  Serial.begin(9600);
  Wire.begin(); // join i2c bus (address optional for master)
  }
  unsigned int integerValue=0;  // Max value is 65535
  char incomingByte;
 
  void loop() { 
  if (Serial.available() > 0) {   // something came across serial   
 
  while(1) {            // force into a loop until 'CR' is received     
    Serial.flush();
  incomingByte = Serial.read();     
  if (incomingByte == 'CR') break;   // exit the while(1), we're done receiving     
  if (incomingByte == -1) continue;  // if no characters are in the buffer read() returns -1     

  Wire.beginTransmission(1); // transmit to device #1
    Wire.write("incomingByte= ");        // sends five bytes         
    Wire.write(incomingByte);              // sends one byte           
    Wire.endTransmission();    // stop transmitting         
    delay(100);
     
}
  }
  }



Slave

#include <Wire.h>

void setup()
{
  Wire.begin(1);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
  Serial.println("Dual VNH5019 Motor Shield");



}

void loop()
{
  delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
 
 
  //if (Wire.available()>0);
  while(1 < Wire.available()) // loop through all but the last
  {
    char c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
  }
  int incomingByte = Wire.read();    // receive byte as an integer
  Serial.println(incomingByte);         // print the integer
  Serial.println("check1");
   
 
 
}

I get the same data misses on the slave Arduino serial monitor. I'm going to see what happens when I exchange the Master Arduino with a new one.






Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 237
Posts: 24276
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code tags.
Use the # symbol on the toolbar.

Please.

Code:
if (incomingByte == 'CR') break
does it seem likely that a single character read will ever equal two characters?
« Last Edit: March 08, 2013, 06:29:46 pm by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok ASCII carriage return, CR is = 13 DEC
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ran new Test code same problem. Shows proper code initially then misses.
Logged

0
Offline Offline
Tesla Member
***
Karma: 114
Posts: 8894
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

#7 below will help you.

http://arduino.cc/forum/index.php/topic,148850.0.html
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Offline Offline
Edison Member
*
Karma: 57
Posts: 2078
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Number 7 is the code tags. Please put your code between the code tags.

I have some serious problems with your code.
The problem is the data flow. Perhaps you can make a abstract drawing of how you want the data flow, without thinking about interrupts or so. After that, make your sketch according to your drawing.

To make it work, make it very simple. Don't use the event in the slave, just check the Wire.available() in the loop and print it. If that is okay, you can use the receiveEvent, but make the code simpler. You have a while that is probably skipped every time, since the I2C data is received one byte after one byte (the I2C 100kHz clock is slow).
« Last Edit: March 08, 2013, 09:37:25 pm by Erdin » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Erdin

I don't think the problem lies with the slave code the slave will putout or print what is given by the master. It appears to be some timing issue on the Master, maybe due to code execution time.

I'm concerned with how the serial buffer is filled and when a character is read or pulled off. Is it loaded with the next new and then holds for a new read before it loads again or does it get to 64 bytes and start dropping unread characters. 

I'm perplexed is there a good manual on Arduino's syntax codes that you know of, I'm learning while doing smiley.

I did install a USB monitor on the Master computer to monitor the code sent to the Master Arduino, BFF's packets are solid. 
   
Logged

Offline Offline
Edison Member
*
Karma: 57
Posts: 2078
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Good to hear the BFF packets are okay.

About the programming, I am kind of lost there. I don't know what you want to do anymore.
I was serious about the code tags, the data flow and the Wire.available() in a loop.

About the Serial communication:
Received data is placed into a buffer.
The Serial.available() return the number of bytes in the buffer.
Using Serial.read() return a byte from the buffer and lowers the number of available bytes.
I didn't know what would happen if the buffer overflows, so I made a test sketch:
Code:
void setup()
{
  Serial.begin( 9600);
  Serial.println("Start");
  delay( 10000 );

  Serial.println("Received:");
  while( Serial.available() > 0)
  {
    Serial.print( (char) Serial.read());
  }
}

void loop()
{
   ;
}

During the 10 seconds wait time, I copied a very long line to the serial monitor.
After that it prints only the first 64 characters. -> correction, it was 63 with Arduino 1.5.2 and Uno.

Conclusion: If the buffer is full, the received characters are discarded.

http://arduino.cc/en/Reference/serial
http://arduino.cc/en/Reference/Wire
« Last Edit: March 28, 2013, 02:23:45 am by Erdin » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Erdin

Here what the Sim software needs to do

Master:
It needs to be able to read BFF's packets into the Master controller.

Out of the packet of the packet the Master needs to get each actuator value ie AB153765320535313 where in this case Act1=53 Act2=76 Act3=53 Act4=20 Act5=53 Act6=53. 

Each actuator value needs to be sent the its Slave controller.

Slave:

The slave controller will need to read the value and evaluate it against the motor's potentiometer (pot) value and turn the motor on in the direction where its pot value will head towards the actuator value ie Act1. That would be either forward, reverse or stop if Act1 is equal to the pot. This would be looped where the motor pot value chases the Act1 value.

Thats Basically it.

I got it the # button for code sorry about that, Im trying the quote.

Quote
the data flow and the Wire.available() in a loop.


Dont follow are you say I would only need it once and do the reads there after?






   
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

[quoteDuring the 10 seconds wait time, I copied a very long line to the serial monitor.
After that it prints only the first 64 characters.

Conclusion: If the buffer is full, the received characters are discarded.
][/quote]

So therefore if Arduino fills the buffer one byte at a time and its full, Bff's bytes will be lost. And the next Bff byte to go into the buffer on the next read (making space available) will in fact be out of sequence. Is that whats happening? Sounds like I need to slow down how fast Bff send it's bytes where the buffer never fills.   
Logged

0
Offline Offline
Tesla Member
***
Karma: 114
Posts: 8894
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

here is how I collect and use servo control data received via the serial port. The servo data packets are delimited by a comma.

Code:
//zoomkat 11-22-12 simple delimited ',' string parse
//from serial port input (via serial monitor)
//and print result out serial port
//multi servos added

String readString;
#include <Servo.h>
Servo myservoa, myservob, myservoc, myservod;  // create servo object to control a servo

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

  //myservoa.writeMicroseconds(1500); //set initial servo position if desired

  myservoa.attach(6);  //the pin for the servoa control
  myservob.attach(7);  //the pin for the servob control
  myservoc.attach(8);  //the pin for the servoc control
  myservod.attach(9);  //the pin for the servod control
  Serial.println("multi-servo-delimit-test-dual-input-11-22-12"); // so I can keep track of what is loaded
}

void loop() {

  //expect single strings like 700a, or 1500c, or 2000d,
  //or like 30c, or 90a, or 180d,
  //or combined like 30c,180b,70a,120d,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >1) {
        Serial.println(readString); //prints string to serial port out

        int n = readString.toInt();  //convert readString into a number

        // auto select appropriate value, copied from someone elses code.
        if(n >= 500)
        {
          Serial.print("writing Microseconds: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.writeMicroseconds(n);
          if(readString.indexOf('b') >0) myservob.writeMicroseconds(n);
          if(readString.indexOf('c') >0) myservoc.writeMicroseconds(n);
          if(readString.indexOf('d') >0) myservod.writeMicroseconds(n);
        }
        else
        {   
          Serial.print("writing Angle: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.write(n);
          if(readString.indexOf('b') >0) myservob.write(n);
          if(readString.indexOf('c') >0) myservoc.write(n);
          if(readString.indexOf('d') >0) myservod.write(n);
        }
         readString=""; //clears variable for new input
      }
    } 
    else {     
      readString += c; //makes the string readString
    }
  }
}

Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

UK
Offline Offline
Shannon Member
****
Karma: 183
Posts: 11114
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The message protocol looks pretty straight forward and makes it easy to detect the start and end of a message. On the serial side I suggest you need to explicitly find the start and end of each message. I think the best way to implement that is as a state machine which keeps track of where you are within the current message and the most obvious way to represent state is as the byte offset with the current message. With this approach you don't actually need to buffer the messages since you can process and then discard each byte as it arrives.

Code:
// incomplete, untested
if(Serial.available())
{
  byte val = Serial.read();

  switch(state)
  {
    case 0:
      if(val == 'A')
      {
        state++;
      }
      else
      {
        // not the expected character
        state = 0;
      }
      break;
    case 2:
      if(val == 'B')
      {
        state++;
      }
      else
      {
        // not the expected character
        state = 0;
      }
      break;
    case 2 .. 8:
      sendActuatorValue(state-2, val);
      state++;
      break;
    default:
      // end of message
      state = 0;
  }
}

It seems that the values you're sending to each slave consist of a single byte so you don't need any fancy encoding there, just write a byte containing the new value for the actuator.

If it's only dealing with serial input the master device will be almost idle. What's the nature of the interface between each slave and its actuator? Have you ruled out driving these directly from the master? If feasible, that would simplify your solution considerably.
« Last Edit: March 10, 2013, 09:02:29 am by PeterH » Logged

I only provide help via the forum - please do not contact me for private consultancy.

Pages: 1 [2]   Go Up
Jump to: