This is a timelapse script for moving a camera along a dolly. The problem is that when I run the code, sometimes (at iteration 7 exactly, for example) the dolly is moving and the camera snaps a photo at the same time. It's as if the commands aren't blocking before the next one gets executed. As you can see, I've tried scattering sleep's in the code to no avail.
Here is the workflow:
Raspberry Pi sends commands to camera (snap photo) and Arduino (move dolly)
The Arduino talks to EasyDriver Stepper Motor Driver, which talks to the stepper and causes dolly to move.
Repeat.
Here is my Python script.
import os, commands, string, gps
from subprocess import Popen, PIPE
from time import sleep
import serial
ser = serial.Serial('/dev/ttyACM0', 9600)
sleep (5)
for i in range(0, 20):
#To write information
steps = 1000*(i+1)
ser.write('1,'+str( steps )+'/n')
sleep (4)
bashCommand = "sudo /home/mh00h/Timelapse/camerareset.sh"
os.system(bashCommand)
sleep (2)
bashCommand = "sudo gphoto2 --capture-image"
os.system(bashCommand)
sleep (1)
There are (potentially) two reasons why this doesn't block as required:
Serial communication is buffered, so as long as the length of the data passed to Serial.write() is smaller than the buffer this call can return before the data is read by the Arduino sketch. In fact, depending on the length of the data and the size of the buffer, several calls to Serial.write() could complete before the Arduino completes any reads.
The Arduino sketch may not block until the stepper motor has completed its movement. It would be useful to see the sketch to determine whether this is the case.
Sleeping between calls can help but even if you can get this to work you'll likely experience odd, non-reproducible behavior.
The solution to both the problems above is to synchronize the actions in your code. For the serial communication this can be achieved by sending a 'finished' message back from the Arduino sketch to the python script which will read from the serial port until it receives this message. How to synchronize the stepper motor with the Arduino sketch (if needed) will depend on how the Arduino to stepper motor communication is coded.
Related
I am writing a python script that communicates with Arduino. Every time I close the python script and I open it again the Arduino is restarted. That is because the serial port is reopened by the script on start, hence my Arduino restarts. Is there a way to open the serial port in the script without restarting the Arduino?
This is my Python code:
import time
import serial
from sys import argv
script,elemento,control =argv
arduino= serial.Serial('COM7',9600)
#while True:
time.sleep(1)
elemento=int(elemento)
control=int(control)
if (elemento>0) & (elemento<10):
print(elemento)
print(control)
if control == 1:
arduino.write(str(elemento))
time.sleep(0.5)
arduino.write(str(control))
elif control == 0:
arduino.write(str(elemento))
arduino.write(str(control))
arduino.close()
The Arduino is reset because the serial port open command is pulsing the DTR line. I have very little python experience, but this link shows dsrdtr as the ninth parameter. By putting a bool there you should be able to make it stop resetting. I'm not sure if you want 0 or 1 so you will have to experiment.
Also, depending on the specific board and your soldering abilities, there is normally a component you can remove from the board to stop the serial port from resetting the board. Be advise that this option makes it harder to upload new firmware since the bootloader uses the reset to start.
Good luck!
I am trying to blink an LED using a router AT XBee which is controlled by a coordinator API Xbee. The coordinator Xbee is connected to a Raspberry Pi which runs the following program. The LED blinks consistently for exactly 4 cycles but after that, it blinks inconsistently (gets stuck and doesnt light and then blinks super fast, again gets stuck). Sometimes, even after the program is stopped, the LED blinks after few seconds. What is causing the delay and inconsistency, I failed to figure out. I'd appreciate any pointers. Thanks.
Baud Rate: 9600
from xbee import XBee, ZigBee
import serial
import time
ser = serial.Serial('/dev/ttyUSB0', 9600)
xbee = ZigBee(ser)
while True:
try:
xbee.send('remote_at',
frame_id='A',
dest_addr_long='\x00\x00\x00\x00\x00\x00\xFF\xFF',
dest_addr='\xFF\xFE',
options='\x02',
command='P2',
parameter='\x05')
time.sleep(1)
xbee.send('remote_at',
frame_id='A',
dest_addr_long='\x00\x00\x00\x00\x00\x00\xFF\xFF',
dest_addr='\xFF\xFE',
options='\x02',
command='P2',
parameter='\x04')
time.sleep(1)
except KeyboardInterrupt:
break
xbee.send('remote_at',
frame_id='A',
dest_addr_long='\x00\x00\x00\x00\x00\x00\xFF\xFF',
dest_addr='\xFF\xFE',
options='\x02',
command='P2',
parameter='\x04')
ser.close()
To start with, try switching from broadcast to unicast packets by setting dest_addr_long (and not setting dest_addr at all). My recollection is that broadcast packets are sent a total of three times to ensure they're received on the remote device. There probably isn't much traffic on your network, but I think you'll see more reliable timing with unicast.
Second, try switching to 115200 bps. It will streamline communication between the Raspberry Pi and coordinator, and eliminate possible serial buffering delays.
I am doing a serial communication in python between a RPi and a camera. I send some data from the RPi using ser.write() and read data from the camera in the RPi using ser.read(). Then I would like to know what would ser.flush(), ser.flushinput() and ser.flushoutput() do if I add these after the read command.
I assume ser.flush() will make the program wait till all data from buffer memory is read. But I don't understand what the other two will do
Can someone tell me, what is the difference between these three when used in serial communication and what will happen when I use each of them separately after the ser.write() or ser.read().
I am attempting to receive data from the qu-bot at http://www.qu-bot.com. The robot has an ATML atmega16 microcontroller. I have written a program that runs on the robot which outputs data to its serial port. The program however stops whenever I connect to the controller. I tested this by adding a beep statement. The robot beeps as long as the program is running. The beeping stops when I connect to the robot. I tried qu-bo support and they suggested disabling the dtr flag on the serial port. I did that but no joy.
Is there anything else I can try?
[start of code running on the qu-bot]
Note:
This is written in some kind of proprietary variant of C which they call quick c.
// This code displays the uart functions.
int main(void)
{
INIT();
UART_INIT(57600);
UART_PRINT("HELLO!!\n");
DELAYS(1);
UART_PRINT("MY NAME IS QU-BOT.\n");
DELAYS(1);
UART_PRINT("HELLO!!\n");
UART_PRINT("YOU ARE USING UART SAMPLE CODES.\n");
while(1)
{
UART_PRINT("test\n");
BEEP();
DELAYS(60);
}
}
now for my python serial port reading program. I have tried this program both on raspbian and on windows 7 64bit. I am pasting the windows version. The raspbian version has a different name for the linux.
import serial
import time
ser=serial.Serial()
ser.port=8
ser.baudrate=57600
ser.setDsrDtr(False)
print 'initialized'
flag = ser.isOpen()
if flag:
print 'port already open.'
pass
else:
ser.open() # opening the port 'ser' that was just created to receive data
time.sleep(0.5)
print 'ready to read'
print ser
ser.write('a')
s=ser.read(4)
print s
ser.close()
Pranav
P.S. I have consulted the following links amongst others.
<https://learn.sparkfun.com/tutorials/terminal-basics/all>
<http://www.plainlystated.com/2013/06/raspberry-pi-serial-console/>
<http://elinux.org/RPi_Serial_Connection>
<https://learn.sparkfun.com/tutorials/terminal-basics/all>
Based on my experience in serial communications with microcontrollers the most likely cause of this problem is that when you connect the serial cable to the robot it causes a phantom byte (due to electrical noise that happens when you make the connection) to look like it's coming from the controller - either this or the controller is sending a legitimate byte to the robot. In either case it is likely that the arrival of a byte at the robot's serial port (even if it was only electrical noise mistaken to be a data byte - this is a very common occurrence) caused the robot's microcontroller to invoke the UART receive interrupt. If you don't have an appropriate UART receive handler (ISR - Interrupt Service Routine) written and linked into the correct interrupt vector then your robot's microcontroller can go off into "deep space" upon the detection of the first incoming serial data byte - and make your robot appear to "hang". If you intend to do "polled" serial communications (your code manually checks for received bytes in its main loop) instead of interrupt-driven (hardware detection of an incoming byte causes your UART Rx ISR to be invoked) then all you have to do is to disable UART interrupts and your problem should go away.
All right, so I am positive my Arduino circuit is correct and the code for it. I know this because when I use the serial monitor built into the Arduino IDE and send 'H' an LED lights up, when I send 'L' that LED turns off.
Now I made a Python program
import serial
ser = serial.Serial("COM4",9600)
ser.write("H")
When I run the code the LED blinks on for a second then goes back off.
However when I do each of these lines separately in the shell it works just like it is supposed to.
Any ideas?
When you open the serial port, this causes the Arduino to reset. Since the Arduino takes some time to bootup, all the input goes to the bitbucket (or probably to the bootloader which does god knows what with it). If you insert a sleep, you wait for the Arduino to come up so your serial code. This is why it works interactively; you were waiting the 1.5 seconds needed for the software to come up.
I confirmed that opening the serial port resets my Arduino Uno; I flashed a program which will blink the LED from the setup() routine -- calling open("/dev/ttyACM0") was sufficient to trigger the reset. This is IMHO a confusing and undocumented wrinkle in the serial support.
I had the same problem and it works if I add a delay of about 2 seconds from opening the serial connection to writing on it, 1 second was not enough.
Just to make it a bit more clear I'll modify the code so everyone can see what needs to be added!
import serial
import time
ser = serial.Serial("COM4",9600)
time.sleep(3)
ser.write("H")
Adding in a sleep statment helps to let the serial open up without any problems!
Assuming you are using an Arduino Uno
The USB port and the Uno serial bus exposed on pins 1 and 0 share the same RX/TX lines. I suggest getting a USB to TTL adapter like the one here so that you can communicate to the Arduino without using the USB port. The Arduino IDE has its own method for disengaging from the USB driver such that a virtual serial port can be created. Have your Ardunio use SoftwareSerial instead.
Here is an example I found on the internet where somebody had clashing bus issues.