I'm trying to send message to arduino via usb cable with python.
#!python3
import serial
import time
import api
import sys
api = api.API()
arduino = serial.Serial('COM3', 115200, timeout=.1)
time.sleep(2)
while api['IsOnTrack'] == True:
if api['Gear'] == 3:
arduino.write('pinout 13')
print "Sending pinon 13"
msg = arduino.read(arduino.inWaiting())
print ("Message from arduino: ")
print (msg)
time.sleep(2)
Arduino:
// Serial test script
int setPoint = 55;
String command;
void setup()
{
Serial.begin(115200); // initialize serial communications at 9600 bps
pinMode(13,OUTPUT);
}
void loop()
{
while(!Serial.available()) {
}
// serial read section
while (Serial.available())
{
if (Serial.available() >0)
{
char c = Serial.read(); //gets one byte from serial buffer
if(c == '\n')
{
parseCommand(command);
command = "";
}
else
{
command += c; //makes the string command
}
}
}
if (command.length() >0)
{
Serial.print("Arduino received: ");
Serial.println(command); //see what was received
}
}
void parseCommand(String com)
{
String part1;
String part2;
part1 = com.substring(0, com.indexOf(" "));
part2 = com.substring(com.indexOf(" ") +1);
if(part1.equalsIgnoreCase("pinon"))
{
int pin = part2.toInt();
digitalWrite(pin, HIGH);
}
else if(part1.equalsIgnoreCase("pinoff"))
{
int pin = part2.toInt();
digitalWrite(pin, LOW);
}
else
{
Serial.println("Wrong Command");
}
}
Python shell looks like this:
http://i.imgur.com/IhtuKod.jpg
Can I for example make the arduino read the message once and the clear the serial?
Or can you spot a clear mistake I have made?
While using just the Arduino IDE serial monitor. The led lights up when I write "pinon 13", this doesn't work while using python. Or when I send "pinout 13" message from serial monitor, it will tell me that it is a "Wrong Command", this also won't happen while using python.
Do you guys have any ideas how I should make the python send the message just once and not contiunously?
In your Python code, you will have to write/send a \n after the command for the Arduino to recognize.
serial.write('pinon 13\n'); should work; note though, that \n may yield different results on different systems (eg. Windows vs. Linux), so you may want to explicitly use the same ASCII code on the Arduino and on the PC.
In Python this should be chr(10) and on the Arduino you may use if(c == 10) if you want.
Related
#include <Servo.h>
String incomingByte ;
Servo frri, frle, reri, rele, frriup, frleup, reriup, releup; // the motors we used, there are 8 motor fr = front, ri = right, le = left, le = left
int frri_speed, frle_speed, reri_speed, rele_speed, frriup_speed, frleup_speed, reriup_speed, releup_speed = 1500; // the motors speed it's between 1000 and 2000 when we send 1500 to motors, they stop
void setup() {
Serial.begin(115200);
frri.attach(3, 1000, 2000);//
frle.attach(8, 1000, 2000);//
reri.attach(5, 1000, 2000);//
rele.attach(6, 1000, 2000);//
frriup.attach(9, 1000, 2000);//
frleup.attach(2, 1000, 2000);//
reriup.attach(7, 1000, 2000);//
releup.attach(4, 1000, 2000);//
frri.writeMicroseconds(1500); // Motors we used is controlled by servo library
frle.writeMicroseconds(1500);
reri.writeMicroseconds(1500);
rele.writeMicroseconds(1500);
frriup.writeMicroseconds(1500);
frleup.writeMicroseconds(1500);
reriup.writeMicroseconds(1500);
releup.writeMicroseconds(1500);
delay(2000);
}
void loop() {
if (Serial.available() > 0) { // checks if there is a message
incomingByte = Serial.readStringUntil('\n'); // its reads the message for example = "15001500194019401500150015001500"
if (incomingByte.length() == 32) {
frri_speed = (incomingByte.substring(0, 4)).toInt();
frle_speed = (incomingByte.substring(4, 8)).toInt();
reri_speed = (incomingByte.substring(8, 12)).toInt();
rele_speed = (incomingByte.substring(12, 16)).toInt();
frriup_speed = (incomingByte.substring(16, 20)).toInt();
frleup_speed = (incomingByte.substring(20, 24)).toInt();
reriup_speed = (incomingByte.substring(24, 28)).toInt();
releup_speed = (incomingByte.substring(28, 32)).toInt();
frri.writeMicroseconds(frri_speed);
frle.writeMicroseconds(frle_speed);
reri.writeMicroseconds(reri_speed);
rele.writeMicroseconds(rele_speed);
frriup.writeMicroseconds(frriup_speed);
frleup.writeMicroseconds(frleup_speed);
reriup.writeMicroseconds(reriup_speed);
releup.writeMicroseconds(releup_speed);
delay(5);
}
}
}
First of all sorry for my bad English, I use pyserial communicate Arduino and Jetson Nano. I send my data which is 32 char of integer like 150015001500150015001500150015001500 to Ardunio. It works until there but Arduino cannot read data fast and correctly.
First of all
Make sure that you don't send any data that are never received from arduino or from python script
Arduino <--> Python communication guide
arduino
I suggest you to use the serialEvent() this function will be called when you are receiving some data
bool stringComplete = false;
String inputString = "";
void serialEvent() {
while (Serial.available())
{
char inChar = (char)Serial.read();
// you can remove this if block if you want your string to contain '\n'
if (inChar == '\n')
{
stringComplete = true;
break;
}
inputString += inChar;
}
}
Then in your loop() you will have something like that
if (stringComplete)
{
//here you have your inputString ready to use
//remember to reset your variable
stringComplete = false;
inputString = "";
}
python script
You will have something like this
import serial
# set up connection
# you have to put your address '/dev/ttyACM0' is an example
ser = serial.Serial('/dev/ttyACM0', 115200, writeTimeout=0)
#send data
ser.write(your_string_data.encode())
I have got PTZ controller, Wemos D1 Mini (based on ESP8266-12F) and Raspberry and I want read data from PTZ using Wemos and send it via wifi to Raspberry. This is my code on RPi:
import socket
s = socket.socket()
# host = socket.gethostname()
host = '192.168.0.26'
port = 9999
s.connect((host, port))
try:
while True:
response1 = s.recv(1024).decode("utf-8")
print(response1)
except KeyboardInterrupt:
s.close()
And my code on Wemos:
#include "ESP8266WiFi.h"
int msg = 0;
String str = String(0,HEX);
bool startReading = false;
String command = "";
const char *ssid = "MyName";
const char *password = "MyPassword";
WiFiServer wifiServer(9999);
void setup() {
Serial.begin(9600);
Serial.setDebugOutput(true);
for(uint8_t t = 4; t > 0; t--) {
Serial.printf("[SETUP] BOOT WAIT %d...\n", t);
Serial.flush();
delay(1000);
}
delay(1000);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting..");
}
Serial.print("Connected to WiFi. IP:");
Serial.println(WiFi.localIP());
wifiServer.begin();
}
void loop() {
WiFiClient client = wifiServer.available();
if (client) {
while (client.connected()) {
msg = Serial.read();
if (msg != -1) {
command = String(msg,HEX);
client.print(command);
}
delay(1);
}
client.stop();
Serial.println("Client disconnected");
}
}
Everything work fine, reaading data from PTZ is immediate but sending data to RPi is slow, I can see significant delay. Reducing the distance from the router does not improve the situation. I tried use #include <WebSocketsServer.h> but this libary is even worse. My question is how I can increase communication speed? Will putting the server on rpi instead of wemos help? Are there any more suitable libraries that I could use?
I'm new to this!!
python code
i = results[1]
i *= 100
if i >= 75:
print('Recognised as owner!')
arduino.write(str.encode('1'))
else:
print('not matches')
serial monitor
111111111111111111111111111111111111111111111111111111111111111111...
Arduino code
#include <Servo.h>
Servo servo;
char value1;
void setup()
{
servo.attach(8);
servo.write(0);
Serial.begin(9600);
}
void loop()
{
if(Serial.available() > 0)
value1 = Serial.read();
Serial.print(value1);
if (value1 == '1') {
digitalWrite(13, HIGH);
servo.write(90);
delay(100);
}
for (int i = 10; i > 0; i--){
Serial.println("go inside!!, hurry up !!");
delay(1000);
}
servo.write(0);
Serial.println("door is closed");
delay(1000);
}
question:
this program can handle the door system based on face recognition
the Arduino takes the value of "1" over and over. so later servo always looping every 10 s. because the program cant handles 1 single value.
my goal is to make sure that the Arduino only get 1 single input. so later the servo is running well
ty
I'm trying to connect python with Arduino code using serial but I cannot call serial.read() within the led_on_off() function.
This is the Arduino code:
int led=13;
int val=0;
char functionname='K';
#include <string.h>
void setup()
{
Serial.begin(9600);
pinMode(led, OUTPUT);
digitalWrite (led, LOW);
Serial.println("Connection established...");
}
void loop()
{
functionname = Serial.read();
if (functionname= 'L')
{
led_on_off();
}
}//void loop
void led_on_off()
{
val=Serial.read()
if (val= 1)
digitalWrite(led,HIGH)
else if (val == 0)
digitalWrite(led,LOW)
}
And this is the python code:
import serial
Arduino_Serial = serial.Serial('com18',9600) # Create Serial port object called arduinoSerialData
print(Arduino_Serial.readline()) # read the serial data and print it as line
print("Enter L to ON LED and M dc motor")
input_data = input()
Arduino_Serial.write(input_data.encode())
print(Arduino_Serial.readline())
input_value=input("enter 1 or 0")
Arduino_Serial.write(input_value.encode())
my expectation is to get input (1 or 0) from python code and process it within the led_on_off function in Arduino code using the serial.read() function and turn on or off the led at pin 13.
As already stated by #KIIV your Arduino code has some syntax errors. Besides that, you are sending a string from your Python script (input function) so you need to read it as a string on Arduino. Something like this would do the job:
Python script:
import serial
# Create Serial port object called arduinoSerialData
Arduino_Serial = serial.Serial('com18', 9600)
# read the serial data and print it as line
print(Arduino_Serial.readline())
input_data = input("Enter L to ON LED and M dc motor: ")
Arduino_Serial.write(input_data.encode())
print("Received Command:", Arduino_Serial.readline())
while True:
input_value = input("enter 1 or 0")
Arduino_Serial.write(input_value.encode())
Arduino code:
int led = 13;
void setup()
{
Serial.begin(9600);
pinMode(led, OUTPUT);
digitalWrite(led, LOW);
}
void loop()
{
//void loop
if (Serial.available())
{
String functionname = Serial.readString();
if (functionname == "L")
{
Serial.println("Command received from Arduino!");
while (1)
{
led_on_off();
}
}
}
}
void led_on_off()
{
if (Serial.available())
{
String val = Serial.readString();
if (val == "1")
digitalWrite(led, HIGH);
else if (val == "0")
digitalWrite(led, LOW);
}
}
Intent: Control arduino uno from serial port
Tools:
https://github.com/JanStevens/ArduinoPi-Python
I got the server working on both my mac and my Model b+ Raspberry.
The browser behaves as shown in the picture below in both situations.
To me it looks like the server sent the message to Arduino successfully. But the data somehow gets lost on the way. The Arduino board resets every time I access the url in my browser. I googled and found that a 10uF capacitor between ground and reset pins would prevent the reset from happening. It did, but pin 3 won't go "HIGH". I got a LED+RESISTOR plugged on pin 3 and ground accordingly. I can see the Rx led blinking every time I access the url. So it makes me think that the Arduino is misunderstanding the command from my Flask sever.
OG Arduino code:
String cmd;
bool cmdRec = false;
void setup()
{
//Start the connection with the Raspberry Pi
Serial1.begin(115200);
// Start the connection with the Laptop, for debugging only!
//Serial.begin(115200);
}
void loop()
{
handleCmd();
}
void serialEvent1() {
while(Serial1.available() > 0) {
char inByte = (char)Serial1.read();
if(inByte == ':') {
cmdRec = true;
return;
} else if(inByte == '#') {
cmd = "";
cmdRec = false;
return;
} else {
cmd += inByte;
return;
}
}
}
void handleCmd() {
if(!cmdRec) return;
// If you have problems try changing this value,
// my MEGA2560 has a lot of space
int data[80];
int numArgs = 0;
int beginIdx = 0;
int idx = cmd.indexOf(",");
String arg;
char charBuffer[20];
while (idx != -1) {
arg = cmd.substring(beginIdx, idx);
arg.toCharArray(charBuffer, 16);
data[numArgs++] = atoi(charBuffer);
beginIdx = idx + 1;
idx = cmd.indexOf(",", beginIdx);
}
// And also fetch the last command
arg = cmd.substring(beginIdx);
arg.toCharArray(charBuffer, 16);
data[numArgs++] = atoi(charBuffer);
// Now execute the command
execCmd(data);
cmdRec = false;
}
// For advanced function like switch all the leds in RGB
void execCmd(int* data) {
switch(data[0]) {
case 101:
{
for(int i = 2; i < (data[1]*2)+1; i+=2) {
pinMode(data[i], OUTPUT);
analogWrite(data[i], data[i+1]);
}
}
break;
case 102:
{
pinMode(data[1], INPUT);
int sensor = analogRead(data[1]);
Serial1.println(sensor);
}
break;
case 103:
{
String result = "";
int sensor = 0;
for(int j = 2; j < data[1]+2; j++) {
pinMode(data[j], INPUT);
sensor = analogRead(data[j]);
result += String(sensor)+",";
}
Serial1.println(result);
}
break;
default:
{
pinMode(data[0], OUTPUT);
analogWrite(data[0], data[1]);
}
break;
}
}
It does not compile this way. So I uncommented the second Serial.begin line and deleted all the "Serial1." appearances on the code. I can't see no action on the arduino IDE serial when I test it on my mac.
As the code was written with an Arduino Mega that got 2 or 3 serial ports, void serialevent1() is triggered when there is communication going on the the MEGA's SERIAL1 port. Since I am working on the UNO, that only have 1 serial port, all i had to do was delete the "1" before the parenthesis and all worked as supposed.
void serialEvent() { }