Последовательная связь между Python и Arduino дает полуслучайные результаты - PullRequest
0 голосов
/ 22 марта 2019

Я пытаюсь заставить Arduino передавать данные в Python с сенсора. Затем, когда эти данные поступают в Python, Python должен отправить сигнал обратно в Arduino, чтобы заставить мотор реагировать на поступающие данные. В настоящее время мой код приводит к этому, однако, если я посмотрю на данные, у меня будут случайные всплески данных, которые не совпадают со сценарием. Например, я помещу нагрузку в 5 ньютонов на датчик, и он будет считывать 5 ньютонов в течение нескольких итераций, затем он будет стремиться к чему-то случайному. Я посмотрел только на выход Arduino в Arduino IDE, и это постоянный и постоянный поток данных. Я посмотрел на то, что получает Python без выходного сигнала, и это дает то же самое, что и Arduino. Я не знаю, почему, когда мне приходится отправлять информацию туда и обратно, я получаю эту проблему. Если у кого-то есть лучшее решение о том, как получить хорошие показания, я был бы признателен.

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.


  }
}
...