Difference between SCmd.readSerial() and Serial.read() - python

Currently I'm trying to Send information from python to Arduino through the serial port.
I manage this using only one letter Serial.read() 'P' and executing an action on my Arduino with the following code.
Arduino code:
#define arduinoLED 12 // Arduino LED on board
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(arduinoLED, OUTPUT); // Configure the onboard LED for output
digitalWrite(arduinoLED, LOW); // default to LED off
}
void loop() {
// put your main code here, to run repeatedly:
//delay (20000);
//char comein=Serial.read();
//Serial.println(comein);
char *arg = "hello";
if (Serial.read()== 'P'){
digitalWrite(arduinoLED, HIGH);
delay(5000);
}
else {
digitalWrite(arduinoLED, LOW);
Serial.println("Hello World");
}
}
Python code:
ser.open()
ser.is_open
my_string='P'
my_string_as_bytes=str.encode(my_string)
print(my_string_as_bytes)
ser.write(my_string_as_bytes)
This works well and turn my LED on but how could I manage more then one letter for the command for example 'P1 2018' for the led to turn on?
But my real problem is that I try to do exactly the same thing, using the same Python code, but using SCmd.readSerial() to read the information in Arduino such as the following:
Arduino code:
#include <SerialCommand.h>
#define arduinoLED 12 // Arduino LED on board
SerialCommand SCmd; // The demo SerialCommand object
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(arduinoLED, OUTPUT); // Configure the onboard LED for output
digitalWrite(arduinoLED, LOW); // default to LED off
SCmd.addCommand("P1", process_command1); // Converts two arguments to integers and echos them back
SCmd.addCommand("P", relay1_on); // Turns Relay1 on
SCmd.addDefaultHandler(unrecognized); // Handler for command that isn't matched (says "What?")
Serial.println("Ready");
}
void loop() {
// put your main code here, to run repeatedly:
SCmd.readSerial(); // We don't do much, just process serial commands
}
void relay1_on()
{
digitalWrite(12, HIGH);
Serial.println(3000);
delay(3000);
digitalWrite(12, LOW);
}
void process_command1()
{
int aNumber = 5;
char *arg = "hello";
Serial.println("We're in process_command");
arg = SCmd.next();
int OhmPosition = atoi(arg); //will return only numbers
arg = SCmd.next();
int relay = atoi(arg); //will return only numbers
arg = SCmd.next();
int opentime = atoi(arg); //will return only numbers
Serial.println(OhmPosition);
Serial.println(relay);
Serial.println(opentime);
}
As you can see, their is Serial command, responding to 'P' which is the same example as above but it doesn't work for some reason and don't understand why. Any idea?
And the second Serial command is 'P1' which is where I would like to get at the end, so I could send from Python something like:
Python code:
my_string6 = 'P1'+str(actions_time_[0][0] )+' '+str(actions_time_[0][1])+' '+str(actions_time_[0][2]))
my_string_as_bytes=str.encode(my_string6)
print(my_string_as_bytes)
ser.write(my_string_as_bytes)
output looks like this=> b'P1 150.0 5.0 2000.0 '
To enable me to start the P1 command and send values, to be saved in OhmPosition, Relay, Time which will be separated by a space, as the goal is to pilot a small electrical automate.
I would be very please to have your support on theses couples of point related to each other.

How can your program tell the difference between receiving the "P1" command and receiving the "P" command followed by some random "1"
You code seems to rely on a library that isn't a standard part of the Arduino install. You should provide a link to where you got the SerialCommand class.

Related

Python serial.write() not working for NodeMCU

I am fairly new to hardware. I want to control an LED light using NodeMCU and Python. I uploaded an Arduino code in nodeMCU and then used pyserial library to get the serial output. But when I try to give input to the port, it doesn't work. I don't know where the problem is.
Here is the arduino code:
int inputVal = 0;
const int ledPin = 5; //D1 pin of NodeMCU
void setup() {
Serial.begin(9600);
delay(100);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, 0);
}
void loop() {
while(Serial.available()>0){
inputVal = Serial.read();
}
Serial.println(inputVal);
if(inputVal==1){
digitalWrite(ledPin, HIGH);
Serial.println("LED is ON");
}
else{
digitalWrite(ledPin, LOW);
Serial.println("LED is OFF");
}
Serial.println("");
}
Here is the python code:
import serial
global ser
ser = serial.Serial("COM8", baudrate=9600, timeout=10,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS)
while(True):
ser.write(bytes(1))
line = ser.readline()
print(line.decode('utf8'))
The output in python comes out to be:
0
LED is OFF
0
LED is OFF
0
LED is OFF
and so on. The ser.write() function isn't writing the value as 1 on the serial port. When I change the value of inputVal in Arduino code, the LED turns on and the output on arduino serial monitor comes as 1 LED is ON, which implies that the circuit connection and Arduino code is working fine.
I also noticed that the COM port that I am using can work with either python or arduino at a time. After uploading the arduino code with inputVal=1, the LED turned on and arduino serial monitor started displaying (1 LED is ON). But, as soon as I ran the python code, the led turned off and the python output came out to be 0 LED is OFF. Please help me.
Also, is there a way for me to control NodeMCU totally by python, without using arduino code first?
the output from python is correct. bytes(integer) creates an array of provided size, all initialized to null in your case size = 1, bytes(1), so the output that you have is 0x00 if you try bytes(10) the out put will be b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'.
what you need to do is to change ser.write(bytes(1)) to ser.write(bytes('1',encoding= 'utf-8')) that should work

Python Serial Communication Arduino Led Controlling Problems

I am trying to control a total of 6 LEDS with python. I was using pyserial to send arduino some data but I have encountered several problems with it.
The first problem I have encountered was:
According to the code I have written on arduino, the LEDS should blink for 1 second for several amount of times a specific data received. (This is later explained below.) However, the LEDS stay on the number of seconds they should blink. Meaning if the LEDS are supposed to blink for 10 times. The LEDS stay on for 10 seconds and turn off.
The second problem was:
The if conditions I have put in the code was not in order. As you can see in the arduino code, the if conditions are in order. However, this is what happens when I run the code.
The first LED lights up for 10 seconds, the second one lights up for 10 seconds as well. And later on the fifth one lights up.
To explain a little more of the code:
I am storing lists inside a list inside of python. There is a for loop that sends each list with a delay of 1 second.
The list has 6 elements.( This is for later experimentation.) However, in this work only the first two of elements of each list matter.
In order to negate the auto reset on arduino, I put 10 microfarad capacitor between the ground and reset. After that I run the python code to send the data.
I think I have explained the situation with details, however I am open to suggestions and will answer questions on the comments.
The Python Code:
import time
import serial
incomingByte2=[[1,20,200,300,400,500],[2,30,24,63,200],[3,5,400,500,100,200],[4,10,1,1,1,1],[5,10,1,1,1,1],[6,10,1,1,1,1]]
uzunluk= len(incomingByte2)
def close():
# arduino=serial.Serial("COM4",9600)
arduino = serial.Serial(
port='COM3',\
baudrate=115200,\
parity=serial.PARITY_NONE,\
stopbits=serial.STOPBITS_ONE,\
bytesize=serial.EIGHTBITS,\
timeout=0)
print("connected to: " + arduino.portstr)
for i in range(0,uzunluk):
arduino.write(str.encode(str(incomingByte2[i])))
time.sleep(1)
The Arduino Code:
int ledPins[] = {2,3,4,5,6,7,8,9};
int incomingdata[6];
int ilkled,ikinciled,ucunculed,dordunculed,besinciled,altinciled;
void setup() {
// put your setup code here, to run once:
int index;
Serial.begin(115200);
for(index = 0; index <= 7; index++)
{
pinMode(ledPins[index],OUTPUT);
}
}
void loop() {
// put your main code here, to run repeatedly:
if(Serial.available()){
for (int a=0; a < 6; a++) {
incomingdata[a] = Serial.parseInt();
delay(100);
ilkled=incomingdata[0];
ikinciled=incomingdata[1];
ucunculed=incomingdata[2];
dordunculed=incomingdata[3];
besinciled=incomingdata[4];
altinciled=incomingdata[5];
}
}
if (ilkled==1){
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[0],HIGH);
delay(1000);
digitalWrite(ledPins[0],LOW);
}
}
if (ilkled==2){
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[1],HIGH);
delay(1000);
digitalWrite(ledPins[1],LOW);
}
}
if (ilkled==3){
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[2],HIGH);
delay(1000);
digitalWrite(ledPins[2],LOW);
}
}
if (ilkled==4){
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[3],HIGH);
delay(1000);
digitalWrite(ledPins[3],LOW);
}
}
if (ilkled==5){
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[4],HIGH);
delay(1000);
digitalWrite(ledPins[4],LOW);
}
}
if (ilkled==6){
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[5],HIGH);
delay(1000);
digitalWrite(ledPins[5],LOW);
}
}
}
I think your read loop is broken. It should close after delay(100), no?
for (int a=0; a < 6; a++) {
incomingdata[a] = Serial.parseInt();
delay(100);
}
Personally I would not string encode the data in Python. Send it as raw bytes, then read it as raw bytes into your int array.
Serial.readBytes( incomingData, 6 ); // assumes 8 bit ints.
That would do away with the loop completely.
Your LED staying on instead of flashing because you missed the line I added below.
for (int x=0;x<ikinciled;x++){
digitalWrite(ledPins[5],HIGH);
delay(1000);
digitalWrite(ledPins[5],LOW);
delay(1000); // <<<< Hold the LOW time
}
Otherwise it will be set LOW for only a few microseconds.
You may also run into synchronous issues with your Serial read versus how much time you spend in "delay()" during the LED flashing. Your python looks like it's sleeping only for 1 second, but your code responding to that will take many seconds as it delays in delay().
The Serial buffer will overflow and data will be lost/overwritten and when you call your next "parseInt" or "readBytes" there is no guarantee where the next bit of data in the buffer starts. Highly likely not at the next block of 6 ints.
You could send the data less often or send it based on how long the flashing will take. Alternatively you could implement an interrupt system to flash the LEDs... and the solutions get more complex from there up.
Welcome to the world of low level communications protocols.
PS, get rid of these
if (ilkled==6){
Just use it directly.
digitalWrite(ledPins[ilkled-1],HIGH);

problem with writing to serial port in python to be used by arduino (to turn on light/move servo etc...)

i'm having trouble on instructing my Arduino to execute different if statements by writing to the serial port in python.
I've currently got an LED and resistor connected in series via the GND and ~5 digital pins. I want to switch the LED on when, using python, I access the serial port (COM6 in my case) and write to the serial port '1' and switch the LED off when I write to serial port '2'.
Arduino code:
void setup()
{
pinMode(5, OUTPUT);
digitalWrite(5, LOW);
Serial.begin(9600);
}
void loop()
{
if (Serial.available() > 0)
{
if (Serial.read() == '1')
{
digitalWrite(5, HIGH);
delay(100);
}
else if (Serial.read() == '2')
{
digitalWrite(5, LOW);
delay(100);
}
}
}
Python code in terminal:
In[1]: import serial
In[2]: ser1 = serial.Serial('COM6', 9600)
In[3] ser1.write('1'.encode())
Out[3]: 1
(Also i dont really understand what the ser1.write(...) command is returning, and the number will change if i try other values in the argument...)
When I try and switch the LED on using
ser1.write('1'.encode())
the LED switches on, happy days.
However when I try and switch it off by writing into the python terminal:
ser1.write('2'.encode())
the LED won't turn off...? help plz!
Calling Serial.read() removes the byte from the buffer. The second call to Serial.read(), to compare to '2', just returns -1, since there is no more data left.
Read it into a variable and compare that.
char c = Serial.read();
if (c == '1')
{
digitalWrite(5, HIGH);
delay(100);
}
else if (c == '2')
{
digitalWrite(5, LOW);
delay(100);
}

Connecting HC-05 Transceiver to MSP430G2 using PySerial

So I've been trying to connect this HC-05 transceiver to my MSP-430G2. Since I'm using a MacBook, I try to send messages using PySerial. I am using:
OS X 10.9.5
Python 2.7
MSP-430G2553
Energia 0101E0016
This is my Energia code:
int gLed = GREEN_LED;
void setup()
{
pinMode(gLed, OUTPUT);
digitalWrite(gLed,LOW);
Serial.begin(9600);
}
void loop()
{
int buf_size = Serial.available();
if (buf_size > 0) {
char input = Serial.read();
if (input == '1'){
digitalWrite(gLed, HIGH);
}
else if (input == '0'){
digitalWrite(gLed, LOW);
}
}
}
After I verify and upload this on the microcontroller, I connect 3.3V to VCC, GND to ground, TXD-RXD from the transceiver to P1.2-P1.1 on the microcontroller (opposite, meaning TXD on transceiver goes into P1.2(RXD) and vice versa), and GND and VCC from the transceiver to the top GND and VCC pins on both sides of the microcontroller. Then I pair my laptop with the HC-05, and I use the following scripts in Python to send messages:
import serial
s = serial.Serial(port='/dev/tty.HC-05-DevB', baudrate=9600)
s.write('1')
What happens is nothing. Absolutely nothing. And it's hard to understand what step I am messing up since it could be any of them. Is it PySerial? Is it how I connect it? Is it my Energia code? Any clue would be greatly helpful. Thank you very much.
UPDATE: This code worked:
void loop()
{
int buf_size = Serial.available();
if (buf_size > 0) {
digitalWrite(gLed, HIGH);
delay(1000);
digitalWrite(gLed, LOW);
delay(1000);
}
}
The LED started blinking after I finished writing the previous Python script. It might be important to note that it only started blinking after I wrote s.write('1') (or any other string as an argument) in Python. Also it doesn't stop after I write s.close() and unpair the HC-05 transceiver from my computer.
I think this means a connection is established but some reason the if statements aren't working as they should. Thanks a lot for all you guys' help. I would really appreciate if someone could help me figure out what is wrong with the message evaluation too.
UPDATE 2: This code also worked:
void loop()
{
int buf_size = Serial.available();
if (buf_size > 0) {
char input = Serial.read();
if (input){
digitalWrite(gLed, HIGH);
delay(1000);
digitalWrite(gLed, LOW);
delay(1000);
}
}
}
Any time I sent an input, the light turned on and then off. It remained off until I sent another input. I think this means the inputs are received by the transceiver and relayed to the microprocessor. The issue might be that the inputs I am sending are not understood by the microprocessor however.
The issue is that I am sending single byte char messages that I had previously determined in my Energia code. I am using Python 2.7 and I tried many different ways to send messages from PySerial including: s.write('1'), s.write(1), s.write(b'1'), s.write('1'.encode()), s.write(bytearray('1')). At this point, I really don't know how to send it in a way that will help me solve this issue, but I believe I was able to narrow it down to PySerial at this point.
UPDATE 3: The situation is getting weirder. After making the MCU blink according to its input I noticed the following situation.
When I used s.write('1') the received binary by the bluetooth transceiver was '11110100.' After this I tried using s.write('2') and s.write('3') and I realized that they were received as the same binary by my MCU: '11110100.' The next thing I did was trying s.write('4') and I realized it gave the same result as s.write('1'). I wrote the following script to try it (also includes the script to print out input by LED blinking).
void loop()
{
int buf_size = Serial.available();
if (buf_size > 0) {
char input = Serial.read();
if (byte(input) == B11110100){
for (int i=0; i < 10; i++){
digitalWrite(rLed, HIGH);
delay(100);
digitalWrite(rLed, LOW);
delay(100);
}
}
else if (input){
digitalWrite(gLed, HIGH);
digitalWrite(rLed, HIGH);
delay(1000);
digitalWrite(gLed, LOW);
digitalWrite(rLed, LOW);
delay(1000);
for (int i=0; i < 8; i++){
int val = bitRead(input,i); // get the voltage from the microphone
if (val == 0){
digitalWrite(rLed, HIGH);
delay(1000);
digitalWrite(rLed, LOW);
}
else if (val == 1){
digitalWrite(gLed, HIGH);
delay(1000);
digitalWrite(gLed, LOW);
}
delay(1000);
}
}
}
}
Both s.write('1') and s.write('4') give the same output. Anyone have any idea what this could be about? Thanks a lot for your help and time.
SOLUTION: I realized Energia wasn't set up to work with my MSP model but a closely related one. Fixing that fixed all issues. Thanks everyone for your help.
I have used an HC-06 to connect the serial port of an Arduino with a MacBook before and the tricky part was finding the right port.
Once its paired, list the available ports with ls /dev/{tty,cu}.* and try a different one. For me it showed two different ports for a single device.

Hanging python script with arduino. Need help simplifying things

Ok so what I'm trying to do is turn an LED on with one python script and off with another one. Now the problem I'm facing is my python script has to keep hanging for the LED to stay on. I can't figure out how to read something from serial, close the coms while leaving the LED on.
'g' is what I'm sending from the on python script and 'h' will be sent from the off python script.
The arduino:
void setup(){
Serial.begin(9600);
pinMode(13, OUTPUT);
Serial.write('g');
Serial.write('h');
}
void loop(){
if(Serial.read() == 'g' ){
digitalWrite(13, HIGH);
Serial.end();
}
if(Serial.read() == 'h' ){
digitalWrite(13, LOW);
Serial.end();
}
}
And the python
#! /usr/bin/python
## import the serial library
import serial
## Boolean variable that will represent
## whether or not the arduino is connected
connected = False
## open the serial port that your ardiono
## is connected to.
ser = serial.Serial("/dev/cu.wchusbserial1410", 9600)
## loop until the arduino is ready
while not connected:
serin = ser.read()
connected = True
ser.write("g")
while ser.read() == 'g':
ser.read()
## close the port
ser.close()
the 'while ser.read() parts at the bottom was just me messing about trying to figure out what I need but so far no such luck.
Thanks in advance!
In python code instead of using this serial command, simply use print command. Suppose you wanna send character g on the serial port then simply write:
print "g"
and it will be sent over to serial port. Worked for me while using Arduino YUN.
Thanks for the feedback. I used a different method and thought it would be a good idea to share the code incase anyone is interested in doing the same.
Python:
import serial
import time
arduino = serial.Serial('/dev/tty.wchusbserial1410', 9600)
time.sleep(0.1) # wait
print("initialising")
arduino.write('off') # turns LED off
print("LED OFF")
time.sleep(0.1) # wait
arduino.close() # close serial
This is the code used to turn the light off. If you want to turn it on, it's the same procedure but create another script replacing arduino.write('off') with arduino.write('on')
And Arduino:
int led = 13; // Pin 13
void setup()
{
pinMode(led, OUTPUT); // Set pin 13 as digital out
// Start up serial connection
Serial.begin(9600);
Serial.flush();
}
void loop()
{
String input = "";
// Read any serial input
while (Serial.available() > 0)
{
input += (char) Serial.read(); // Read in one char at a time
delay(5); // Delay for 5 ms so the next char has time to be received
}
if (input == "on")
{
digitalWrite(led, HIGH); // on
}
else if (input == "off")
{
digitalWrite(led, LOW); // off
}
}
The one problem with this script is after the serial coms close the light turns off. To fix this, I used a 10uF electrolytic capacitor between the ground and reset pin to keep the serial port open. (Please note: only put the cap in AFTER you've programmed the Arduino. If you need to reprogram, pull it out first.)

Categories