Back and Forth Communication Issue with Python and Arduino - python

I am developing a code that is suppose to take data from a load cell and based on that data it should control a motor. If the load cell reads a specific value the motor should rotate one direction, if it reads a different value it should go in the other direction. Right now if I apply a load to the sensor the motor will go in one direction, when the load is removed the motor will not go the other way. Instead it continues to go in the wrong direction. I am also having python save the data from the load cell to a csv file and because of that I have noticed that the load cell value stays at a high number like 117 newtons even when the force from the load cell is removed. Before having the communication between arduino and python the output of the sensor was spot on. I have read a little on duplexing and was thinking maybe there in lies my problem. Any help on why my python force value is wrong now would be great.
I have tried a different format to making my arduino code. Arduino Code 2 works, better, I can get the motor to respond to the inputs on the load cell, however as I print the data coming into python it does get a little screwed up. This does not affect my motor surprisingly though. I intend on keeping this incoming data for future use and was hoping that it could be cleaned up. For example lets say that I have 5 newtons of force on there it will display 5 newtons for a few seconds then it will spike to a random number for a couple instances then back to normal.
Python
import serial
import csv
import time
from time import localtime, strftime
import warnings
import serial.tools.list_ports
__author__ = 'Matt Munn'
arduino_ports = [
p.device
for p in serial.tools.list_ports.comports()
if 'Arduino' in p.description
]
if not arduino_ports:
raise IOError("No Arduino found - is it plugged in? If so, restart computer.")
if len(arduino_ports) > 1:
warnings.warn('Multiple Arduinos found - using the first')
Arduino = serial.Serial(arduino_ports[0],9600,timeout=1)
time.sleep(2)
start_time=time.time()
Force = []
Actuator_Signal=[]
outputFileName = "Cycle_Pull_Test_#.csv"
outputFileName = outputFileName.replace("#", strftime("%Y-%m-%d_%H %M %S", localtime()))
with open(outputFileName, 'w',newline='') as outfile:
outfileWrite = csv.writer(outfile)
while True:
while (Arduino.inWaiting()==0):
pass
try:
data = Arduino.readline()
dataarray = data.decode().rstrip().split(',')
Force = round(float(dataarray[0]),3)
print (Force)
if Force < 50:
Arduino.write(b'u')
print ('up')
else:
Arduino.write(b'd')
print('down')
except (KeyboardInterrupt, SystemExit,IndexError,ValueError):
pass
outfileWrite.writerow([Force,"N"])
Arduino
#include <HX711_ADC.h>
#include "CytronMotorDriver.h"
// Configure the motor driver.
CytronMD motor(PWM_DIR, 3, 2); // PWM = Pin 3, DIR = Pin 2.
int up = HIGH;
int down = LOW;
int dstate = up;
int python_direction = 0;
float interval = 12000;
float pretime= 0;
float curtime = 0;
// LOAD CELL
//HX711 constructor (dout pin, sck pin)
HX711_ADC LoadCell(11, 12);
float force;
float calforce;
float newtons;
// The setup routine runs once when you press reset.
void setup() {
Serial.begin(9600);
LoadCell.begin();
LoadCell.start(2000); // tare preciscion can be improved by adding a few seconds of stabilising time
LoadCell.setCalFactor(100); // user set calibration factor (float)
}
// The loop routine runs over and over again forever.
void loop() {
if (Serial.available()>0){
python_direction = Serial.read();
Serial.print (python_direction);
Serial.print (",");
}
LoadCell.update();
force = LoadCell.getData();
force = (force/285); // Force in (N) // 285 is conversion factor
calforce = (-1.0389*force)+0.0181, // This is in lbs
newtons = 4.45*calforce;
receive from serial terminal for tare
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay();
}
unsigned long curtime = millis();
if (python_direction == 'u'){
motor.setSpeed(255); // Run forward at full speed.
}
if (python_direction == 0){
motor.setSpeed(0); // Stop motor.
}
if (python_direction == 'd'){
motor.setSpeed(-255); // Run backward at full speed.
}
Serial.println(newtons);
}
Arduino 2
#include <HX711_ADC.h> // HX711 Library
#include "CytronMotorDriver.h"
// Configure the motor driver.
CytronMD motor(PWM_DIR, 3, 2); // PWM = Pin 3, DIR = Pin 2.
int up = HIGH;
int down = LOW;
int dstate = up;
int python_direction = 0;
float interval = 12000;
float pretime= 0;
float curtime = 0;
HX711_ADC LoadCell(11, 12);
float force;
float calforce;
float newtons;
void setup() {
Serial.begin(9600);
LoadCell.begin();
LoadCell.start(2000); // tare preciscion can be improved by adding a few seconds of stabilising time
LoadCell.setCalFactor(100.0); // user set calibration factor (float)
}
void loop() {
LoadCell.update();
forceRead();
actuatorControl();
}void forceRead()
{
force = LoadCell.getData();
force = (force/285); // Force in (N) // 285 is conversion factor
calforce = (-1.0389*force)+0.0181, // This is in lbs
newtons = 4.45*calforce;
Serial.println(newtons);
//receive from serial terminal for tare
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay();
}
}
void actuatorControl(){
if (Serial.available()>0){
python_direction = Serial.read();
Serial.print (python_direction);
Serial.print (",");
}
if (python_direction == 'd'){
motor.setSpeed(255); // Run forward at full speed.
}
if (python_direction == 0){
motor.setSpeed(0); // Stop motor.
}
if (python_direction == 'u'){
motor.setSpeed(-255); // Run backward at full speed.
}
}

Related

Read multiple arduino's using a Raspberry Pi 3 through USB

I have 3 arduino's that have RC522 rfid readers attached to them. They each have their own power supplies and they are connected to a raspberry pi 3 via the usb ports. I am getting really inconsistent results when running the reader in python. It does appear all 3 are reading but the loop does some weird things. Sometimes the chip code keeps repeating after the chip is removed and other times it works properly. There does not appear to be any consistency with which arduino is behaving oddly either.
Any help would be greatly appreciated!!!
Here is the arduino code (The same code was copied to each arduino with the exception of the initial println that indicates which arduino is connected).
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 5 // Configurable, see typical pin layout above
#define SS_PIN 53 // Configurable, see typical pin layout above
#define MOSI_PIN 51
#define MISO_PIN 50
#define SCK_PIN 52
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
MFRC522::MIFARE_Key key;
String read_rfid;
void setup() {
Serial.begin(9600);
SPI.begin(); // Init SPI bus
rfid.PCD_Init(); // Init MFRC522
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF;
}
Serial.println(F("The Toy Maker's Sanctuary RDIF Reader 1 Online."));
//Serial.println(F("Using the following key:"));
//printHex(key.keyByte, MFRC522::MF_KEY_SIZE);
}
void loop() {
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
if ( ! rfid.PICC_IsNewCardPresent())
return;
// Select one of the cards
if ( ! rfid.PICC_ReadCardSerial())
return;
dump_byte_array(rfid.uid.uidByte, rfid.uid.size);
Serial.println(read_rfid);
}
/*
Helper routine to dump a byte array as hex values to Serial.
*/
void dump_byte_array(byte *buffer, byte bufferSize) {
read_rfid = "";
for (byte i = 0; i < bufferSize; i++) {
read_rfid = read_rfid + String(buffer[i], HEX);
}
}
Here is the python code
import serial
ser0=serial.Serial("/dev/ttyACM0", 9600, timeout=1)
ser1=serial.Serial("/dev/ttyACM1", 9600, timeout=1)
ser2=serial.Serial("/dev/ttyACM2", 9600, timeout=1)
ser0.baudrate=9600
ser1.baudrate=9600
ser2.baudrate=9600
read_ser0=""
read_ser1=""
read_ser2=""
while True:
read_ser0=ser0.readline()
print("0: ",read_ser0)
read_ser1=ser1.readline()
print("1: ",read_ser1)
read_ser2=ser2.readline()
print("2: ",read_ser2)
read_ser0=""
read_ser1=""
read_ser2=""

Python to Arduino Serial Communication Yields Semi-random Results

I am trying to get an Arduino to give data to Python form a sensor. Then when this data is received into Python, Python needs to send a signal back to the Arduino to get a motor to react to the incoming data. Presently my code results in this, however if I look at the data I will have random spikes of data that do not coincide with the scenario. For example I will place a 5 newton load on the sensor and it will read 5 newtons for several iterations, then it will spike to something that is random. I have looked at just the Arduino output in the Arduino IDE and it is a steady and constant stream of data. I have looked at what Python receives without having the out going signal and that gives the same thing as the Arduino. I don't know why when I have to two send information back and forth I get this issue. If anyone has a better solution on how to get good readings I would appreciate it.
Python
import serial
import csv
import time
import sys
from time import localtime, strftime
import warnings
import serial.tools.list_ports
__author__ = 'Matt Munn'
arduino_ports = [
p.device
for p in serial.tools.list_ports.comports()
if 'Arduino' in p.description
]
if not arduino_ports:
raise IOError("No Arduino found - is it plugged in? If so, restart computer.")
if len(arduino_ports) > 1:
warnings.warn('Multiple Arduinos found - using the first')
Arduino = serial.Serial(arduino_ports[0],9600,timeout=1)
time.sleep(2)
start_time=time.time()
Force = []
Actuator_Signal=[]
Cycle_Count=[]
state = True
Up = True
numPoints = 10
ForceList = [0]*numPoints
AvgForce = 0
#This allows the user to input test conditions.
Force_Input = input("What is the force you want to test with in Newtons?")
Cycles = input("How many cycles would you like to run?")
Material = input("What kind of material is to be tested?")
print("The test will be conducted with", Force_Input, " Newtons of force and for a total of" , Cycles, " cycles.", " on", Material)
print ("REMOVE HANDS AND OTHER OBJECTS AWAY FROM AREA OF OPERATION.")
print("Testing will begin.")
time.sleep(5)
start_time = time.time()
#This creates the unique file for saving test result data.
outputFileName = " Cycle_Pull_Test_#.csv"
outputFileName = outputFileName.replace("#", strftime("%Y-%m-%d_%H %M %S", localtime()))
with open(outputFileName, 'w',newline='') as outfile:
HeaderNames = ['Material','Newtons','Time']
outfileWrite = csv.DictWriter(outfile, fieldnames = HeaderNames)
outfileWrite.writeheader()
#This takes the data from the arduino and interprits it.
while True:
while (Arduino.inWaiting()==0):
pass
try:
data = Arduino.readline()
dataarray = data.decode().rstrip().split(',')
for i in range(0,numPoints):
Force = abs(round(float(dataarray[0]),3))
ForceList[i] = Force
AvgForce = round((sum(ForceList)/numPoints),3)
elapsed_time = round(time.time()-start_time,3)
print (AvgForce, elapsed_time)
#This Controls the actuators direction based on the force input on the loadcell.
if AvgForce > float(Force_Input):
Up = False
state = True
Arduino.write(b'd')
else:
Arduino.write(b'u')
Up = True
if state == True and Up == True:
state = False
Cycles = float(Cycles) + 1
if Cycles >= float(Cycle_Count[0]):
Arduino.write(b'o')
print("Testing is done.")
time.sleep(1)
sys.exit("All the data will be saved now")
except (KeyboardInterrupt, SystemExit,IndexError,ValueError):
pass
#This writes the data from the loadcell to a csv file for future use.
outfileWrite.writerow({'Material' : Material, 'Newtons' : AvgForce, 'Time' :elapsed_time })
Arduino
#include <HX711_ADC.h> // HX711 Library
#include "CytronMotorDriver.h"
// Configure the motor driver.
CytronMD motor(PWM_DIR, 3, 2); // PWM = Pin 3, DIR = Pin 2.
int up = HIGH;
int down = LOW;
int dstate = up;
int python_direction = 0;
float interval = 12000;
float pretime= 0;
float curtime = 0;
HX711_ADC LoadCell(11, 12);
float force;
float calforce;
float newtons;
void setup() {
Serial.begin(9600);
LoadCell.begin();
LoadCell.start(2000); // tare preciscion can be improved by adding a few seconds of stabilising time
LoadCell.setCalFactor(100.0); // user set calibration factor (float)
}
void loop() {
LoadCell.update();
forceRead();
actuatorControl();
}void forceRead()
{
force = LoadCell.getData();
force = (force/285); // Force in (N) // 285 is conversion factor
calforce = (-1.0389*force)+0.0181, // This is in lbs
newtons = 4.45*calforce;
Serial.println(newtons);
//receive from serial terminal for tare
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay();
}
}
void actuatorControl(){
if (Serial.available()>0){
python_direction = Serial.read();
Serial.print (python_direction);
Serial.print (",");
}
if (python_direction == 'd'){
motor.setSpeed(255); // Run forward at full speed.
}
if (python_direction == 0){
motor.setSpeed(0); // Stop motor.
}
if (python_direction == 'u'){
motor.setSpeed(-255); // Run backward at full speed.
}
}

Cannot send/receive number through USB to Arduino to control a motor

I'm having a project to use pyserial to send a number to an Arduino. This number is RPM (round per minute). Arduino will receive this number to control the motor (in here I use PID Controller) and then send the number Arduino received back to Python console. The problem is, I tried to send float number to Arduino, but it receives nothing. Here is the problem:
#include <TimerOne.h>
#include <Encoder.h>
#define A 2 //Encoder pins
#define B 3
Encoder encoder(2,3);
//Config pins for motor control:
int pinAIN1 = 9; //Direction
int pinAIN2 = 8; //Direction
int pinPWMA = 5; //Speed
int pinSTBY = 4; //Stanby
float receive;
float tsamp = 0.01;
float xung = 0;
float last_xung = 0;
float current_speed = 0;
float ref_speed ; //The reference speed
float error = 0;
float last_error = 0;
float PID,last_PID;
float Kp =0.15 , Ki =0, Kd = 0.01;
void dotocdo()
{
if ( ref_speed >= 0)
{
digitalWrite(pinAIN1, 1);
digitalWrite(pinAIN2, 0);
analogWrite(pinPWMA, PID);
}
if ( ref_speed < 0)
{
digitalWrite(pinAIN1, 0);
digitalWrite(pinAIN2, 1);
analogWrite(pinPWMA, abs(PID));
}
float P;
static float I,D;
current_speed = 60*(xung-last_xung)/(tsamp*374*4);
last_xung = xung;
Serial.println(current_speed);
error=abs(ref_speed)-abs(current_speed);
P = Kp*error;
D = Kd*(error - last_error)/tsamp;
I = Ki*error*tsamp;
PID = last_PID + P + I + D;
last_error = error;
last_PID = PID;
if (PID >= 255) {PID = 255;}
if (PID <= -255) {PID = -255;}
}
void setup() {
Serial.begin(115200);
pinMode(pinPWMA, OUTPUT);
pinMode(pinAIN1, OUTPUT);
pinMode(pinAIN2, OUTPUT);
pinMode(pinSTBY, OUTPUT);
pinMode(A, INPUT);
pinMode(B, INPUT);
digitalWrite(pinSTBY, 1);
Timer1.initialize(10000);
Timer1.attachInterrupt(dotocdo);
}
void loop()
{
if (Serial.available())
{
receive= Serial.parseFloat();
ref_speed=receive;
Serial.println(receive);
}
xung=encoder.read();
}
And here is the Python code on Raspberry:
import time
import socket
import sys
import serial
import struct
UNO_1 = serial.Serial('/dev/ttyUSB0', 115200)
while (1):
n=float(25)
UNO_1.write(bytes(b'%f'%n))
receive=UNO_1.readline()
print(receive)
This is the error (Arduino receives nothing):
Does anyone know how to fix this problem?
Has any communication worked before?
Double-check your connections (swapped TX and RX, forgot GND)
Try using a serial terminal (I think pyserial has a demo included) to send data manually.
Your Python script may just be timing out.
Your Python script might be sending too many zeroes or control characters that Serial.parseFloat() does not like (it stops if it does not like something).
Alternativley, just get started with echo programs that don't actually try to parse numbers to see if any data comes through: try this.

Arduino to Raspberry Pi serial communication creates only random chars after a few seconds

For my project I need a Raspberry Pi to communicate with several peripheral components, two of them are Arduinos. The one which causes my problem is a Pro Mini 3.3 V ATmega328. The Arduino receives input from two sensors and transfer the data to the Raspberry Pi via serial. A Python code with the serial-package is used on the Raspberry which establishes a connection every 50 ms.
When the input to the Raspberry is printed, the first few lines are correct but after about two, three seconds the printed lines are random chars.
My Python code looks like this:
import serial
ser = serial.Serial('/dev/ttyS0', 115200, timeout=1)
if ser.isOpen():
ser.close()
ser.open()
...
# loop
try:
ser.write("1")
ser_line = ser.readline()
print ser_line
...
The Arduino code:
#include <Wire.h>
#include "SparkFunHTU21D.h"
#include <FDC1004.h>
FDC1004 fdc(FDC1004_400HZ);
HTU21D myHumidity;
int capdac = 0;
void setup() {
Wire.begin();
Serial.begin(115200);
myHumidity.begin();
}
void loop() {
String dataString = "";
dataString += String(myHumidity.readHumidity());
dataString += " ";
dataString += String(myHumidity.readTemperature());
dataString += " ";
for (uint8_t i = 0; i < 4; i++){
uint8_t measurement = 0;
uint8_t channel = i;
fdc.configureMeasurementSingle(measurement, channel, capdac);
fdc.triggerSingleMeasurement(measurement, FDC1004_400HZ);
//wait for completion
delay(15);
uint16_t value[2];
if (! fdc.readMeasurement(measurement, value)) {
int16_t msb = (int16_t) value[0];
int32_t capacitance = ((int32_t) 457) * ((int32_t) msb);
capacitance /= 1000; //in femtofarads
capacitance += ((int32_t) 3028) * ((int32_t) capdac);
dataString += String(capacitance);
dataString += " ";
int16_t upper_bound = 0x4000;
int16_t lower_bound = -1 * upper_bound;
if (msb > upper_bound) {
if (capdac < FDC1004_CAPDAC_MAX)
capdac++;
} else if (msb < lower_bound && capdac > 0) {
capdac--;
}
}
}
Serial.println(dataString);
delay(20); // delay in between reads for stability
}
The output of this loop looks like:
So the output loses accuracy and become random chars after about six lines and the output doesn't recover. When I print the serial output in the Arduino's serial monitor the output stays correct all the time. After several tests I run out of ideas. Has anyone a solution for this problem or experienced a similar behavior?

want to build web site by django for take a value by Temperature sensor on particle-Photon

i want to build an web site by djnago. this site could be able to take values from Temperature sensor which is connection with my particle-Photon. i checked the net but i do not found an compatible libary Which could be connect my Photon and django framwork. is there any helpful libary to do this .
my "Temperature.ino" code:
#include <OneWire.h>
OneWire ds = OneWire(D4); // 1-wire signal on pin D4
unsigned long lastUpdate = 0;
float lastTemp;
void setup() {
Serial.begin(9600);
// Set up 'power' pins, comment out if not used!
pinMode(D3, OUTPUT);
pinMode(D5, OUTPUT);
digitalWrite(D3, LOW);
digitalWrite(D5, HIGH);
}
// up to here, it is the same as the address acanner
// we need a few more variables for this example
void loop(void) {
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;
if ( !ds.search(addr)) {
Serial.println("No more addresses.");
Serial.println();
ds.reset_search();
delay(250);
return;
}
// The order is changed a bit in this example
// first the returned address is printed
Serial.print("ROM =");
for( i = 0; i < 8; i++) {
Serial.write(' ');
Serial.print(addr[i], HEX);
}
// second the CRC is checked, on fail,
// print error and just return to try again
if (OneWire::crc8(addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return;
}
Serial.println();
// we have a good address at this point
// what kind of chip do we have?
// we will set a type_s value for known types or just return
// the first ROM byte indicates which chip
switch (addr[0]) {
case 0x10:
Serial.println(" Chip = DS1820/DS18S20");
type_s = 1;
break;
case 0x28:
Serial.println(" Chip = DS18B20");
type_s = 0;
break;
case 0x22:
Serial.println(" Chip = DS1822");
type_s = 0;
break;
case 0x26:
Serial.println(" Chip = DS2438");
type_s = 2;
break;
default:
Serial.println("Unknown device type.");
return;
}
// this device has temp so let's read it
ds.reset(); // first clear the 1-wire bus
ds.select(addr); // now select the device we just found
// ds.write(0x44, 1); // tell it to start a conversion, with parasite power on at the end
ds.write(0x44, 0); // or start conversion in powered mode (bus finishes low)
// just wait a second while the conversion takes place
// different chips have different conversion times, check the specs, 1 sec is worse case + 250ms
// you could also communicate with other devices if you like but you would need
// to already know their address to select them.
delay(1000); // maybe 750ms is enough, maybe not, wait 1 sec for conversion
// we might do a ds.depower() (parasite) here, but the reset will take care of it.
// first make sure current values are in the scratch pad
present = ds.reset();
ds.select(addr);
ds.write(0xB8,0); // Recall Memory 0
ds.write(0x00,0); // Recall Memory 0
// now read the scratch pad
present = ds.reset();
ds.select(addr);
ds.write(0xBE,0); // Read Scratchpad
if (type_s == 2) {
ds.write(0x00,0); // The DS2438 needs a page# to read
}
// transfer and print the values
Serial.print(" Data = ");
Serial.print(present, HEX);
Serial.print(" ");
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
Serial.print(data[i], HEX);
Serial.print(" ");
}
Serial.print(" CRC=");
Serial.print(OneWire::crc8(data, 8), HEX);
Serial.println();
// Convert the data to actual temperature
// because the result is a 16 bit signed integer, it should
// be stored to an "int16_t" type, which is always 16 bits
// even when compiled on a 32 bit processor.
int16_t raw = (data[1] << 8) | data[0];
if (type_s == 2) raw = (data[2] << 8) | data[1];
byte cfg = (data[4] & 0x60);
switch (type_s) {
case 1:
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
celsius = (float)raw * 0.0625;
break;
case 0:
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
// default is 12 bit resolution, 750 ms conversion time
celsius = (float)raw * 0.0625;
break;
case 2:
data[1] = (data[1] >> 3) & 0x1f;
if (data[2] > 127) {
celsius = (float)data[2] - ((float)data[1] * .03125);
}else{
celsius = (float)data[2] + ((float)data[1] * .03125);
}
}
// remove random errors
if((((celsius <= 0 && celsius > -1) && lastTemp > 5)) || celsius > 125) {
celsius = lastTemp;
}
fahrenheit = celsius * 1.8 + 32.0;
lastTemp = celsius;
Serial.print(" Temperature = ");
Serial.print(celsius);
Serial.print(" Celsius, ");
Serial.print(fahrenheit);
Serial.println(" Fahrenheit");
// now that we have the readings, we can publish them to the cloud
String temperature = String(fahrenheit); // store temp in "temperature" string
Particle.publish("temperature", temperature, PRIVATE); // publish to cloud
delay(5000); // 5 second delay
}
I think you can send data through HTTP from your photon(mostly, I've heard of it), and using HTTP calls you can push data to your Django application.
On Django side, use djangorestfraework for building APIs.
I do not have any idea about Particle-Photon but basically your .ino extension shows that your file is Arduino file.
Arduino can be connected to python via serial communication. In Django framework you can use that serial communication to get the temperature sensor data and return your logic applied data in JSON format ( by using django rest framework ) to get back data in arduino ( in your case particle photon ).

Categories