Delay in Serial Communication when talking between Arduino and Python - arduino

I have an Arduino-controlled robot with a gyroscope, and I'm trying to send data from it over to a Python program run on a Raspberry Pi. However, there's a 1-2 second delay between me moving the robot, and info being printed out the python program. I've tried restarting my computer, as well as replugging the wires. Is there anything I'm doing in my code that is causing this or is it a hardware thing?
The robot is connected to a Raspberry Pi, with which I have a headless setup. The python program is being run on the Pi but can be viewed on my desktop over SSH. The program has no delay when I connect the robot to my desktop and run the python program on it as well.
Arduino Program:
#include <robot's file>
Gyro gyro; //Object using an imported class
void setup() {
Serial.begin(115200);
while (!Serial) {}
}
void loop() {
gyro.read(); //Reads the robot's yaw and puts it into variable "z"
Serial.println(gyro.z);
}
Python Program:
import serial
from serial.serialutil import SerialException
ser = serial.Serial("/dev/ttyACM0", 115200)
try:
ser.open()
except SerialException:
print("Port already opened")
while True: print(ser.readline())

looks to me that everything is good in your code.
Most of the delay is related to your PC computing time.
If you want to speed up the process I would suggest to interface an Oled display (or an LCD) to display directly your data: using your PC is good for the initial testing, but if you need immediate response it is better to manage the data interfacing directly.
This link may support you: https://www.waveshare.com/wiki/1.3inch_OLED_HAT All the best

After some testing, I think I've figured it out.
Printing to terminal takes a long time, which made the Arduino program faster than the Python program, creating a buildup of data, causing the delay. I've fixed the problem by only printing out data every 10 iterations. The problem would also be fixed if I stored the data into a variable, and did not call the print() function.

Related

Arduino: Detect code info

Is there any way to detect the code version or any info like last updated or size of code or size of binary code?
Here is example:
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
// turn the LED on (HIGH is the voltage level)
delay(1000);
// wait for a second
digitalWrite(LED_BUILTIN, LOW);
// turn the LED off by making the voltage LOW
delay(1000);
// wait for a second
}
If I upload code to Arduino board, can I detect any info inside Arduino regarding the size of the code or the last modified time or upload time etc?
Thanks.
Compilation date is stored in the __DATE__ macro, the current system time at compilation is stored in the __TIME__ macro. Also useful may be the __FILE__ macro, which stores the filename. Reference (and other relevant macros): http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_preprocessor.Pre-defined_macros.html
There is some interesting discussion about something along these lines here:
https://github.com/arduino/Arduino/issues/5618
In that thread they're discussing ways to store the Git hash of the code at the time of the compilation/upload. If you're using Git version control that information would probably be more useful than last modified time or code size for determining which version is running on your microcontroller and being able to easily retrieve that version. I'm not sure how crazy I am about automatically doing a commit on every upload by you could always squash them later once testing is finalized. If you don't use Git, the same techniques could be adapted to adding any other version information you like and even doing automatic backups of the code at that version.
As explained by facchinm in that thread, recent versions of the Arduino IDE provide hooks throughout the build process that you can use to add additional actions. See:
https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification#pre-and-post-build-hooks-since-ide-165
The original proposal is to store the version information in EEPROM. I believe the most common way to do this is via an .eep file. A problem with this idea is that the popular Optiboot bootloader used by the Arduino Uno as well as popular 3rd party hardware packages does not support writing to EEPROM during uploading (in order to fit the bootloader in a 0.5 kB boot section). You would also need to avoid conflicts caused by use of the same EEPROM addresses by the sketch.
The other thought was to instead store it in the code itself. I guess this would be done by using a hook to automatically update a header file "library" that is included by the sketch. e.g.:
#include <VersionTracker.h>
Now how do you access that information? You could have code in the sketch that sends out that information on request or startup. A simple example:
void setup() {
Serial.begin(9600);
Serial.print(F("Filename: "));
Serial.println(F(__FILE__));
Serial.print(F("Compilation timestamp: "));
Serial.println(F(__DATE__ " " __TIME__));
}
void loop() {}
Will print this information to the Serial Monitor on startup. Of course you could use any other method of communication. This sort of thing will add some significant overhead so it would perhaps be preferable (if less beginner friendly) to download the firmware from the microcontroller and then figure out a way to find the version information from the disassembly.
The time you cannot get. The Arduino doesn't have any clock or any way to know the time.
The code size you could get if you use AvrDude to read the hex code back off the chip and then just look at the size of what you read back.

Reliably kick Arduino Micro to bootloader

I have a Arduino Micro connected via usb to my pc, showing up as /dev/arduino.
Now when I want to program it (it currently has the default bootloader from Arduino) I have to boot it into the bootloader. AFAIK this can be done by either resetting the chip or talking to it using the baudrate 1200.
For this I have a script like
#!/usr/bin/env python
import serial
s = serial.Serial(
port="/dev/arduino",
baudrate=1200,
bytesize=serial.EIGHTBITS,
stopbits=serial.STOPBITS_ONE,
parity=serial.PARITY_NONE)
s.isOpen()
s.close()
The problem is, that the script as well as the reset pin do not work reliably. Also cutting the power source from the device usually does not kick it into bootloader.
How can I reliably put my Arduino Micro into bootloader? Preferably over USB.
The Python script you posted really should work. You did not say what your evidence is for why it is not working so I can only guess what might be the problem. My guess would be that you need to add a delay after closing the port because it will take some time for the computer to detect the bootloader, enumerate it, and create the serial ports for it. A delay of one or two seconds ought to be enough.
Another guess would be that the code you are running on your Arduino Micro interferes with USB interface. For example, you might have an interrupt service routine that runs for a long time or you might be disabling interrupts in your mainline code for a long time. If you don't let the Arduino's USB interrupts run promptly, they cannot do their job reliably.
the magic isn't within the arduino IDE but instead on the avrdude sequence.
you can install another avrdude on your system, or use the same one which comes with arduino, but you can make a reset simulating a small signature read with avrdude (avrdude -c arduino -p m328p -P com1)...
but to be completely honest, the real trick is on the arduino's reset circuit. the reset pin is connected to serial DTR via a capacitor (and sometimes rts), so each time avrdude switch the serial configuration to program via rs232 it produce a small pulse on DTR (about 50ms it seems) which causes a reset on the microcontroller. i think you can use s.setDTR(True); time.sleep(0.05); s.setDTR(False) to generate a small pulse to reset your arduino within python...
good luck

Arduino: Using the watchdog for both preventing failures and energy savings

I came across this website when trying to find a reliable way to use the watchdog for preventing failures (code lock ups) and saving battery using an Arduino.
I tried the code and it worked fine. However, i would also like to use the serial monitor. I tried adding Serial.begin(9600); in the setup, however, most of what is shown in the serial monitor (from the code within the main loop) are strange characters (the baud rate is set to 9600). Is this something to do with the function to configure the wdt and the placement of Serial.begin(9600) in the code?
I'd also like to use an external interrupt (via a button on Digital pin 3) to wake the board from sleep. How can be achieved based on the current code? I know how to implement using a different method of making the board go to sleep without using any watchdog at all, however, i have been unsuccessful in making it work with this code.
Many thanks for any help.
As said above, the serial communication should work fine. Are you sure you are able to make your serial communication work fine without the watchdog part of the code? I have used the watchdog tips given on the website along with serial communications without any problem on Arduino Uno, so I would guess the serial communication problem lies somewhere else in your code.
Can you write a bare bone example of your code with the watchdog management part, a serial communication or two somewhere in your loop(), and if you want some delays / infinite loops to test the watchdog firing, post it here, test it on your board and indicate if / where you have problems?
I have never used a pin interrupt, but it seems that google gives some nice results with example code. Have you tried the results given by google?
https://www.arduino.cc/en/Reference/AttachInterrupt
http://www.allaboutcircuits.com/technical-articles/using-interrupts-on-arduino/
You will have to be careful regarding the choice of the pin on which you put the interrupt, as explained in the Arduino Reference only pins 2 and 3 support interrupt on the Uno.

How do i run a system() command using arduino sketch program?

So, here is the thing. I have written an arduino sketch program and this is what i want say if the LED blinks then say the following code is executed such as
system("c:\temp\capture.txt") something like that. Is there a way to do that?
void loop()
{
val = digitalRead(2);
if(val == HIGH)
{
digitalWrite(LED,HIGH)
//system command happens here
}
}
How do i do that? Thanks
Arduino won't be able to execute programs in PC directly because its system is isolated from PC. That's why Arduino can run programs without PC (standalone).
Consider developing a host program that run on your PC and accept comnands via serial communication, and send comnand to execute something from Arduino to the host program. Then, have the host program execute the program to run.

Raspberry Pi w/ Archlinux: C program freezes when writing to serial port

I've got an Arduino attached to my Raspberry Pi which runs on Archlinux ARM, and I'm using a simple C program that reads and writes to the serial bus to the Arduino (/dev/ttyACM0).
This worked fine as long as I had the Arduino attached to my PC, but when I use the Raspberry Pi instead, reading still works but writing will freeze as soon as the buffer is flushed or the connection closed.
This very basic C example atually causes such a freeze:
If the fflush() command is in there it will freeze there, if it's removed then it'll instead freeze at fclose().
FILE *fp;
fp = fopen("/dev/ttyACM0", "wb");
..error handling..
fprintf(fp, "%c", 'B'); /* write the character 'B' to the serial port)
fflush(fp); /* optional, if more write operations follow, in an actual program */
fclose(fp);
Reading from the bus works fine.
I also tried the program "minicom" as it is often suggested for testing serial connections, and it yielded the same results: Sending from Arduino to Pi is fine, trying to type in a character on Pi side -> freeze.
I have tried lots of different stuff on opening/configuring such as replacing the simple fopen() sequence shown above by:
fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_NDELAY);
fcntl(fd, F_SETFL, 0);
if (fd == -1) {
printf("couldn't open serial port.\n");
return -1;
}
fp = fdopen(fd, "w");
and also changing some canonical something parameters (not sure what I'm actually doing there) but to no avail. It will just keep freezing as soon as the Pi tries to write a character to the serial bus.
I've also made sure that all TTYs are unused on the Pi via
ps -ef | grep -i tty
to exclude any silly getty/agetty interference.
And I've tested it without any additional hardware plugged in, to make sure that it isn't a symptom caused by the power supply not being able to sustain everything connected to the Pi, as someone suggested to me.
By now I'm totally out of ideas except that the hardware is maybe just faulty. But that's hard to believe, is it? (And I don't have a replacement to test.)
UPDATE:
When using above alternate sequence and removing the fcntl() line, the C program no longer freezes on writing:
fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
printf("couldn't open serial port.\n");
return -1;
}
fp = fdopen(fd, "w");
So at first I was happy, but actually the written data never arrives on the Arduino side! :(
first of all, rasPI cannot work directy from a PC USB as they are limited below the rasPI need, so you need an external power supply (i used one from a smartphone, now i'm using a plugged usb hub)
Changes are that plugging your arduino drains too much power, and the arduino's and rasPi chip beave randomly. Check if, when the program freeze, the serial port used is still there (check with dmesg, maybe it has been plugged/uplugged)
If your power source are fine, then explain what you mean by freeze; the rasPi freeze or only the code. Eiter case it is a fault on the rasPi side, try updating OS and firmware; the serial does not check if someone is reciving, so flush should only hang the time necessary to write the buffer, even if no one is reading.
remeber that close(), will always call flush(), so use flush() only if really needed. (like in this case, for debugging purpoise :) )

Resources