UNO WiFi over Telnet - wrong characters interpreted, but they seem right.

Hi all,

I am having trouble with code recognition over Telnet (Wifi). I have tried different Telnet programs on both my Mac and on my iPad. If anyone can chime in, I would really appreciate it =)
I have spent a little over a day trying to fix this, but I can’t seem to look at the code the right way to make any progress.
And yes, I have googled, browsed the forum and read the rules for posting!

I want to achieve this:
By typing “start” or “stop” (without the “”), the program should turn On/Off an LED and type a message to the serial monitor. The purpose is only to have a working code for sending and reading commands over telnet, and the code will be expanded upon later in the process with added commands and functions.

Longterm goal:
I want to use my iPad as a smartPad for my robot arm (still in the making). I have got two stepper motors running simultaneously to different positions using the AccelStepper library (acceleration and deceleration), and the program accepts input from the Serial console in terms of positions (“P1”, “P2” and so on). The motors and the main code will be run off a Mega 2560, but I am going to use the Uno WiFi for accepting and translating commands from telnet (relayed to the Mega).
First off though, I need to get the telnet program to work properly… =)

History:
I got everything to work if I used the ‘String’ class, but ended up with a low memory warning and eventually some erratic behaviour. I googled and lurked around, and learned enough to switch to the Char class instead.

The problem:
I can’t get the program to properly recognise the right combination of characters. It receives them and re-prints them both in the Serial and WiFi console correctly, but the “if” statements won’t execute properly. If I type “start” and hit enter, the program reprints it like “start” in both WiFi and Serial monitors - they appear to be the same! But, in the program there is an if-statement looking for if (receivedChars == “start”) { do stuff } that doesn’t execute, but instead the if (receivedChars != “start”) { do stuff } executes.
I have tried adding “\n”, “\r” and “\r\n”, but it made no difference.

What i have:
The program looks for the “\n” marker to get what’s in the WiFi.read, and I tried with the “\r” and a combination of both, but neither worked.

My code (borrowed and adapted, not written from the ground up):

#include <UnoWiFiDevEd.h>

#define LED 12

const byte numChars = 32;
char receivedChars[numChars]; // an array to store the received data

boolean newData = false;

int X = 0;
int Y = 0;

void setup() {

  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
  Serial.begin(9600);
  Wifi.begin();
  Wifi.println();
  Wifi.println(F("___________________________________"));
  Wifi.println(F("Enter 'start' for start or 'stop' for stop, execute with 'Enter':"));
}

void loop() {
  recvWithEndMarker();
  showNewData();
}

void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;

  // if (Serial.available() > 0) {
  while (Wifi.available() > 0 && newData == false) {
    rc = Wifi.read();

    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }
  }
}

void showNewData() {

  if (newData == true  && (receivedChars != "start" || receivedChars != "stop")) {
    Wifi.print(F("Invalid command received: "));
    Wifi.println(receivedChars);
    Serial.print(F("Invalid command received: "));
    Serial.println(receivedChars);
    newData = false;

  }

  if (newData == true && receivedChars == "start") {
    Wifi.print(F("Command received: "));
    Wifi.println(receivedChars);
    Wifi.println(F("System started."));
    digitalWrite(LED, HIGH);
    newData = false;
  }

  if (newData == true && receivedChars == "stop") {
    Wifi.println(F("System stopped."));
    digitalWrite(LED, HIGH);
    delay(500);
    digitalWrite(LED, LOW);
    delay(500);
    digitalWrite(LED, HIGH);
    delay(500);
    digitalWrite(LED, LOW);
    delay(500);
    digitalWrite(LED, HIGH);
    delay(500);
    digitalWrite(LED, LOW);
    delay(500);
    digitalWrite(LED, HIGH);
    delay(500);
    digitalWrite(LED, LOW);
    newData = false;
  }

}
  if (newData == true && receivedChars == "stop") {

receivedChars is a string. That is, it is a NULL terminated array of chars. The comparison here is comparing the address of the array to the address of the string literal. Obviously, they are not the same. strcmp() is used to compare strings.

PaulS:

  if (newData == true && receivedChars == "stop") {

receivedChars is a string. That is, it is a NULL terminated array of chars. The comparison here is comparing the address of the array to the address of the string literal. Obviously, they are not the same. strcmp() is used to compare strings.

Thank you, I got it to work through the serial monitor just fine! The results are not the same when using Telnet though, I have no clue as to why. I did read somewhere that port 23 might force the client to send characters not displayed, and that altering the port might get rid of this behaviour. I don’t know the level of truth in that tho. Besides, i don’t think it’s possible to change the telnet port on the Uno Wifi (please prove me wrong).

[UPDATE] It seems that almost every single one of the telnet clients I tried on iOS (surely at least twenty of them) only two transmitted the right characters. Most of them had no option of sending “\n”, but even some of the ones that did still couldn’t get it right. I guess the Uno Wifi is a picky little bugger!
I won’t post the names of the apps that worked for me here, but for those interested, shoot me a message and I’ll let you know. [/UPDATE]

If anyone tries the following code, just change from Serial. to Wifi. on line 34 and 35 to flip between telnet and serial.

This is the new code (no LED at this time):

 #include <UnoWiFiDevEd.h>
#include <string.h>

const byte numChars = 32;
char receivedChars[numChars]; // an array to store the received data

boolean newData = false;

void setup() {
  Wifi.begin();
  Serial.begin(9600);
  Serial.println("Serial monitor connected.");
  Serial.println();
  
  Wifi.println();
  Wifi.println(F("___________________________________"));
  Wifi.println(F("Enter 'start' or 'stop', execute with 'Enter':"));
  
  Serial.println("Waiting for command from WiFi");
  Serial.println();
}

void loop() {
  recvWithEndMarker();
  showNewData();
}

void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;

  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();

    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }
  }
}

void showNewData () {
  char str1[15];
  char str2[15];
  int start_ret;
  int stop_ret;


  strcpy(str1, "start");
  strcpy(str2, "stop");

  start_ret = strcmp(str1, receivedChars);
  stop_ret = strcmp(str2, receivedChars);

  if (newData == true  && (start_ret == 0 && stop_ret != 0)) {
    Serial.println("A valid command has been entered: ");
    Serial.println(receivedChars);
    Serial.println();
    Wifi.println("A valid command has been entered: ");
    Wifi.println(receivedChars);
    Wifi.println();    
    Serial.println("Program Started");
    Serial.println();
    Wifi.println("Program Started");
    Wifi.println();
    newData = false;
  } else if (newData == true  && (start_ret != 0 && stop_ret == 0)) {
    Serial.println("A valid command has been entered: ");
    Serial.println(receivedChars);
    Serial.println();
    Wifi.println("A valid command has been entered: ");
    Wifi.println(receivedChars);
    Wifi.println();    
    Serial.println("Program Stopped");
    Serial.println();
    Wifi.println("Program Stopped");
    Wifi.println();
    newData = false;
  } else if (newData == true  && (start_ret != 0 || stop_ret != 0)) {
    Wifi.println("Invalid command: ");
    Wifi.println(receivedChars);
    Wifi.println();
    Serial.println("Invalid command: ");
    Serial.println(receivedChars);
    Serial.println();
    Wifi.println();
    Wifi.println(F("___________________________________"));
    Wifi.println(F("Enter 'start' or 'stop', execute with 'Enter':"));  
    Serial.println("Waiting for command from WiFi");
    Serial.println();
    newData = false;
  }

}
  char str1[15];
  char str2[15];
  int start_ret;
  int stop_ret;


  strcpy(str1, "start");
  strcpy(str2, "stop");

  start_ret = strcmp(str1, receivedChars);
  stop_ret = strcmp(str2, receivedChars);

Something wrong with

int start_ret = strcmp("start", receivedChars);
int stop_ret = strcmp("stop", receivedChars);

?

PaulS:
Something wrong with

int start_ret = strcmp("start", receivedChars);

int stop_ret = strcmp("stop", receivedChars);



?

Nothing wrong whatsoever, just remnants from the C++ Sketch I found when reading up on the strcmp function :wink:

Thanks for pointing it out though, code looks sleeker now =)

from "man telnet"

When connecting to ports other than the telnet port, telnet does not attempt telnet protocol negotiations. This makes it possible to connect to services that do not support the telnet protocol without making a mess.

if you lose patience with the limited possibilities of the UnoWiFiDevEd library, try changing firmware or program the on-board esp8266 with Arduino IDE with my Uno WiFi Serial1 library