0

I'm currently designing a system for my GCSE coursework. For the coursework, I am making a bollard system, controlled by the internet / traffic lights.

I've been experimenting with an Arduino Uno and Ethernet shield, in order to fulfill the control by the internet.

When I telnet into my Arduino, and send it the command "S#UP", the red LED comes on, and stays on for 30 seconds. If I send the command again, the Arduino does not turn on the LED, unless the command was send twice, consecutively. Also, if I were to send a different command, for example "S#DOWN", the LED does not even turn on, no matter how many times I send it.

Does anyone have any ideas for my? Anything I've blatantly missed or got myself confused on?

#include <SPI.h>
#include <Ethernet.h>
String authcode, newstatus, command;  
bool UP, DOWN, EMERGANCY;
long UPTime, DOWNTime, EMERGANCYTime, LastFlash;
bool NextFlash;

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

IPAddress ip(192, 168, 1, 177);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

EthernetServer server(1265);

char serverHost[] = "LambdaLaptop";
EthernetClient phpClient;



int R = 8;
int G = 9;

void setup() {
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
  Serial.begin(9600);
  Serial.println("=----------------------=");
  Serial.println("=- Traffic Management -=");
  Serial.println("=-    System Loaded   -=");
  Serial.println("=----------------------=");

  Serial.println("");

  authcode = String("4b4fec50eaa13b98934c36863293b5cf");
  LastFlash = millis();
  NextFlash = HIGH;

  pinMode(R, OUTPUT);
  pinMode(G, OUTPUT);
}

void loop() {
  EthernetClient client = server.available();
  if (client) {
    if (client.available() > 0) {
      char thisChar = client.read();
      command += thisChar;
      ProcessCMD( command );
    }else{
     if(command.length() > 0 ){
       command = String("");
     }
    }
  }
  if( UP ){
    if( UPTime > millis() ){
      digitalWrite(G, HIGH);
    }else{
      UP = false;
      digitalWrite(G, LOW);
    }
  }else if( DOWN ){
    if( DOWNTime > millis() ){
      digitalWrite(R, HIGH);
    }else{
      DOWN = false;
      digitalWrite(R, LOW);
    }
  }else if( EMERGANCY ){
   if( EMERGANCYTime > millis() ){
     if( LastFlash + 100 < millis() ){
       digitalWrite(R, NextFlash);
       if(NextFlash == LOW){
         NextFlash = HIGH;
       }else{
         NextFlash = LOW;
       }
     }
    }else{
      EMERGANCY = false;
      NextFlash = HIGH;
      digitalWrite(R, LOW);
    }
  }  
}

void ProcessCMD( String CMD ){
  if(CMD == "S#UP"){
    UP = true;   
    UPTime = millis() + 30000;
    if(CMD.length() > 11){
      command = String("");
    }
  }else if(CMD == "S#DOWN"){
    // Make the thing go DOWN.
    // GREEN LIGHT
    DOWN = true;
    DOWNTime = millis() + 30000;
    if(CMD.length() > 11){
      command = String("");
    }
  }else if(CMD == "S#EMERGANCY"){
    // Make the thing go DOWN.
    // Flash RED beacon.
    EMERGANCY = true;
    EMERGANCYTime = millis() + 15000;
    if(CMD.length() > 11){
      command = String("");
    }
  }else if(CMD == "TEST"){
    UP = true;
  }else if(CMD == "TEST2"){
    UPTime = millis() + 30000;
  }else{
    if(CMD.length() > 11){
      command = String("");
    }
  }
}

void SetStatus( String newstatus ){
  if (phpClient.connect(IPAddress(192,168,1,10), 80)) {
    phpClient.println(String("GET /setstatus.php?authcode=") + authcode + String("&status=") + newstatus + String(" HTTP/1.1"));
    phpClient.println("Host: LambdaLaptop");
    phpClient.println("User-Agent: arduino-ethernet");
    phpClient.println("Connection: close");
    phpClient.println();
    phpClient.stop();
  }
  else {
    Serial.println("Couldn't connect to the system!");
    phpClient.stop();
  }
}
  • Two things: don't use String it is very inefficient and messy. Secondly, you have misspelled "emergency". – Majenko Jul 6 '15 at 18:08
  • 1
    Another problem is with your times. Not only should they be unsigned long (or better, uint32_t), but your method of dealing with elapsed time will fail at millis() rollover. – Majenko Jul 6 '15 at 18:14
  • 1
    A third issue: your whole method of building up (and clearing, and indeed everything about) your command string is flawed. What's so special about the magical number 11...? – Majenko Jul 6 '15 at 18:16
0

It would be far better to use char arrays instead of the String class (perhaps 11 bytes, if that is the largest command?).

eg.

const int MAX_COMMAND = 11;

char command [MAX_COMMAND];


 if (client.available() > 0) {
      char thisChar = client.read();
      command += thisChar;
      ProcessCMD( command );

You appear to be processing the command for every received byte. This means you will process "S", "S#", "S#D", "S#DO" etc. You need to wait until the whole command has arrived.

Then, once the command has been processed, empty out the command ready for next time.


void ProcessCMD( String CMD ){

Also all upper-case is usually reserved for constants, not variables like CMD.


Finally, your detection of end-time by addition will fail when millis() wraps. This might not matter in a small test, but you may as well teach the right way. Instead of adding an interval, remember the start time and detect when the interval is up, eg. instead of:

if( UPTime > millis() ){

You would write:

if (millis () - UPTime >= 30000) {

Where UPTime is now the start of the interval (that is, you remember when the interval starts, and do the above subtraction to find the end of it).


References

0

I do not have and ethernet shield at this moment to test on it your code but hopefully the next observations will help to solve your issue.

If I send the command again, the Arduino does not turn on the LED, unless the command was send twice, consecutively.

It seems that your string is not correctly processed, probably caused by "garbage" from previous received string or incomplete string. I think is from this part of the code

 if (client.available() > 0) {
  char thisChar = client.read();
  command += thisChar;
  ProcessCMD( command );

You are trying to append a char (one byte) to your command string; by doing this you are not getting the received string necessarily because the "+=" is for retrieve char by char (for example, inside a while loop). First try to print thisChar variable to ensure what are you getting and also you can print client.available() to see how many bytes you got.

Second, for your ProcessCMD function it could be better to use pointers to handle the command variable, meanwhile you must clean command variable always (and not only when CMD.lenght > 11 ), i.e,

if(CMD.length() > 11){
  command = String("");
}

must be at the end of the ProcessCMD function

  command = String("");

Also you can ensure that when you set UP=true, also set DOWN=false and so on. I prefer the Switch-Case structure to handle commands.

Try to follow arduino examples to better understand.

Cheers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.