I have problems converting a string to an int on the Arduino IDE on the UDOO. Seems like sscanf and atoi and String.toInt do not work. They compile correctly with no errors but then lock the board at boot time (no write is displayed, even those before the instruction). Sample code: Code: #include <stdio.h> void setup() { Serial.begin(9600); delay(500); Serial.println("boot"); } void loop() { int pin=0; Serial.println("ready"); // sscanf("1234","%d",&pin); Serial.println("scanf done"); Serial.println(pin); delay(500); } This code works perfectly until you uncomment the sscanf line. After that, the script locks the board completely, no println istruction is shown, not even "boot" at startup. The defult String To Integer example (in the examples menu on the IDE) locks the arduino as well. It seems that the inclusion of the libraries themselves locks the programs at startup (or the locks the serial port?). I have read that there were problems with floats and that using the UDOO as an external arduino connected to another computer might solve some issues. I am wondering if a recompile/install of the ide wouldn't solve it, but what sources and how..? Any idea of why or a workaround? Meanwhile I'll hardcode a home made atoi() function in the code.. Thanks, Francesco
Suggested workaround (don't know if it will work) - Try using a Arduino IE on an external PC (with the patch).
Thank you, I may try that, although now I have rewritten all the str-to-int functions so it doesn't require libraries, and it actually works. Compile, flash, open serial monitor, adjust speed rate and all works, you can set/get any digital or analog pin from the serial monitor! Now I have another problem with the serial.. though it works quite fine in the IDE Serial Monitor, I can't find a way to print/receive to serial from linux shell/scripts, tried all the samples and googled a lot but no way, yet. What am i missing?? How do I take control of the serial port? Thanks! P.S: here is the code of the Sketch : https://github.com/francescom/Pilot.ino
Thank you for posting your code in the last post, found my bug in my Arduino code. To make the Linux work for you the following will work. ubuntu@udoo:~$ sudo ln -sf /dev/ttymxc3 /dev/ttyS0 ubuntu@udoo:~$ exec 3<>/dev/ttyS0 #include <iostream> #include <stdio.h> #include <termios.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/objdetect/objdetect.hpp" #include "opencv2/gpu/gpu.hpp" #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <termios.h> #include <SerialStream.h> #include <sstream> #include <string> #include <errno.h> #include <termios.h> #include <unistd.h> #define height_f 240 #define width_f 320 using namespace std; using namespace cv; using namespace LibSerial; char key; FILE *mytempfile; int set_interface_attribs (int fd, int speed, int parity) { struct termios tty; memset (&tty, 0, sizeof tty); if (tcgetattr (fd, &tty) != 0) { return -1; } cfsetospeed (&tty, speed); cfsetispeed (&tty, speed); tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars // disable IGNBRK for mismatched speed tests; otherwise receive break // as \000 chars tty.c_iflag &= ~IGNBRK; // ignore break signal tty.c_lflag = 0; // no signaling chars, no echo, // no canonical processing tty.c_oflag = 0; // no remapping, no delays tty.c_cc[VMIN] = 0; // read doesn't block tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls, // enable reading tty.c_cflag &= ~(PARENB | PARODD); // shut off parity tty.c_cflag |= parity; tty.c_cflag &= ~CSTOPB; tty.c_cflag &= ~CRTSCTS; if (tcsetattr (fd, TCSANOW, &tty) != 0) { return -1; } return 0; } void set_blocking (int fd, int should_block) { struct termios tty; memset (&tty, 0, sizeof tty); if (tcgetattr (fd, &tty) != 0) { return; } tty.c_cc[VMIN] = should_block ? 1 : 0; tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout if (tcsetattr (fd, TCSANOW, &tty) != 0) { } } void digitalWrite(int fd, bool truth) { if(truth) { write (fd, "run\n", 4); } else { write(fd,"stop\n",5); } usleep(2000); char buf [1000] =""; char n = read (fd, buf, sizeof(buf)); // read up to 100 characters if ready to read char var = buf[0]; String crap = ""; int j = 0; while(j<1000) { var = buf[j]; crap+=var; if(var=='\n') { j=1000; } j++; } cout<< crap; usleep(2000); } int main() { //setup serial char *portname = "/dev/ttyS0"; int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { return 0; } set_interface_attribs (fd, B115200, 0); // set speed to 115,200 bps, 8n1 (no parity) set_blocking (fd, 0); // set no blocking waitKey(1500); cout << "test program" << endl; String whatever = ""; usleep(2000); char buf_clean [1000] =""; char n = read (fd, buf_clean, sizeof(buf_clean)); // read up to 100 characters if ready to read //now flushed while(true) { digitalWrite(fd, true); sleep(2);//some delay digitalWrite(fd, false); key = cvWaitKey(1); //Capture Keyboard stroke if (char(key) == 27) { break; //If you hit ESC key loop will break. } } return 0; } Hope this helps, it's a bit rough and if anyone can help optimise it and help me remove the usleeps it would be awesome.
The arduino code to make this work; **sorry for the fluff, it's from another project with other things going on** //setup for blinking led with command serial volatile int count = 30; volatile boolean toggle = false; volatile boolean running = false; volatile int laser_duty = 900; volatile int laser_period_us = 1000; String inputString = ""; // a string to hold incoming data String inputDigit = ""; // a string to hold incoming numberical data boolean stringComplete = false; // whether the string is complete int led = 13;//pin led is on //boolean flag //String inputString = ""; // a string to hold incoming data //boolean stringComplete = false; // whether the string is complete void setup() { // initialize serial: Serial.begin(115200); delay(500); // inputString.reserve(200); // inputDigit.reserve(200); Serial.println("\n[pulse_demo]"); // reserve 200 bytes for the inputString: pinMode(led,OUTPUT); digitalWrite(led,LOW); Serial.println("ready to start"); } void loop() { if(Serial.available()) { // get the new byte: int inDig = Serial.read(); char inChar = (char)inDig; // add it to the inputString: inputString += inChar; if(isDigit(inDig)) { inputDigit += (char)inDig; } // if the incoming character is a newline, set a flag // so the main loop can do something about it: if (inChar == 0xA || inChar == 0xD) { stringComplete = true; } } //Serial.println("ready to start"); // print the string when a newline arrives: if (stringComplete) { Serial.println("you entered "+inputString); if(inputString.indexOf("run")!=-1) { digitalWrite(led,HIGH); } if(inputString.indexOf("stop")!=-1) { digitalWrite(led,LOW); } if(inputString.indexOf("period")!=-1) { laser_period_us = inputDigit.toInt(); Serial.print("Laser PWM Period = "); Serial.print(laser_period_us); Serial.println(" microseconds"); } if(inputString.indexOf("duty")!=-1) { laser_duty = inputDigit.toInt(); Serial.print("Laser Duty cycle = "); double fraction = (double)(laser_duty)*laser_period_us/1023; Serial.print(fraction); Serial.println(" microseconds"); } // clear the string: inputString = ""; inputDigit = ""; stringComplete = false; } }
Don't forget ubuntu@udoo:~ exec 3>&- this is apparently the correct way to stop comms from the terminal. You can add the terminal commands in c++ code as well.