Go Down

Topic: Switch case and software serial (Read 506 times) previous topic - next topic

beginit

Hi all,
I am trying to write a sketch that will allow me to control a few of the digital outputs on a Uno via the serial port (USB). No problem there, using single chancters and switch case for any characters after a serial event.

My issue is that one of the cases, for example if I send a ASCII g I want all the following serial characters received by the uno to be forwarded to pin 10 and 11 software serial wise. Then if I send a very specific character e.g. G it exits the loop and again allows for control of the digital pins.

I got something like this working already, and will try and post the code shortly.. (not on same computer now). The issue is I am loosing characters when I send data to the uno that do not get forwarded to the software serial port.... I think because of the while loop I have it in....

Any ideas?... thanks for the help :)

robtillaart

Many ideas, but I wait for your code ...
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

beginit

Here is the code. Sorry its just cut and paste, computer is acting up so using tablet....

Thanks in advance... any help would be great :)


int SerialinByte = 0;
  // Software Serial Setup
  SoftwareSerial mySerial(10, 11); // RX, TX
 
void setup() {
  // initialize serial communication (control):
  Serial.begin(9600);
   // initialize Relay Pins:
  int Ignition = 4;
  int Battery = 5;
 
  mySerial.begin(38400);
}
void loop() {
  if (Serial.available() > 0) {
    int inByte = Serial.read();
    switch (inByte) {
    case 'a':   
      digitalWrite(4, HIGH);
      break;
    case 'b':   
      digitalWrite(5, HIGH);
      break;
    case 'A':   
      digitalWrite(4, LOW);
      break;
    case 'B':   
      digitalWrite(5, LOW);
      break;
   case 'c':   
      VIPassing();
      break;
 
 
    default:
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
    }
  }
}
void VIPassing() // pass just data to the unit
{
   do
  { 
      SerialinByte = Serial.read();
     
          if (mySerial.available())
         {
           Serial.write(mySerial.read());
         }
        
         if (Serial.available())
         {
           mySerial.write(Serial.read());
         }
        
  }
  while (SerialinByte != 33);
}

robtillaart

when there is only the c typed in the monitor it is read by this line first

int inByte = Serial.read();

then VIPassing()  is called

and the first thing it does is

SerialinByte = Serial.read();

while there is no byte in the buffer. This makes SerialInByte -1, which is not equal to 33

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

PeterH

You're right that the problem is here:

Code: [Select]

void VIPassing() // pass just data to the unit
{
   do
  {
      SerialinByte = Serial.read();
     
          if (mySerial.available())
         {
           Serial.write(mySerial.read());
         }
       
         if (Serial.available())
         {
           mySerial.write(Serial.read());
         }
       
  }
  while (SerialinByte != 33);
}


I suggest you get rid of the global, and do it something like this:

Code: [Select]

void VIPassing() // pass just data to the unit
{
  char c = 0;
  while(true)
  {
    // wait for a character to arrive
    while(Serial.available() == 0)
    {
      // do nothing
    }
    c = Serial.read();
    if(c == '!')
    {
      break; // out of the enclosing while loop
    }
    else
    {
      mySerial.write(c);
    }
  }
}
I only provide help via the forum - please do not contact me for private consultancy.

beginit

I am pretty sure I follow you code, my concern is that it does not address bi-directional communication, and simply forwards everything to the my serial unless its the exit clause...  am I understanding the code properly...

Thanks form the help guys :)



You're right that the problem is here:

Code: [Select]

void VIPassing() // pass just data to the unit
{
   do
  {
      SerialinByte = Serial.read();
     
          if (mySerial.available())
         {
           Serial.write(mySerial.read());
         }
       
         if (Serial.available())
         {
           mySerial.write(Serial.read());
         }
       
  }
  while (SerialinByte != 33);
}


I suggest you get rid of the global, and do it something like this:

Code: [Select]

void VIPassing() // pass just data to the unit
{
  char c = 0;
  while(true)
  {
    // wait for a character to arrive
    while(Serial.available() == 0)
    {
      // do nothing
    }
    c = Serial.read();
    if(c == '!')
    {
      break; // out of the enclosing while loop
    }
    else
    {
      mySerial.write(c);
    }
  }
}


beginit

Totally understood, but my goal was to exit the main loop and enter the VIPassing loop... if only one character got lost in the transition that would be fine, but once in the loop I would expect everything to pass right ???

Thanks form the help


when there is only the c typed in the monitor it is read by this line first

int inByte = Serial.read();

then VIPassing()  is called

and the first thing it does is

SerialinByte = Serial.read();

:)while there is no byte in the buffer. This makes SerialInByte -1, which is not equal to 33



Go Up