I am new to programming and serial communication, so forgive me for likely messing up something simple.
The script I am writing is reading temperature data sent via serial port from an Arduino. When it first loads up, the Arduino sketch sends a "menu" with options for reading, writing, and clearing EEPROM.
When I load the python script, sometimes it works well enough. Other times, it just doesn't read anything. And other times, it floods my terminal with temp reading data for about 5 seconds, then it sends the menu and acts normally.
I have added the flushinput and time delays, but to no avail.
Another quick question: if I'm in the while loop collecting data from serial, which is without end, how would I be able to enter a command to pause and switch to another part of the program without interrupting the data stream? For example, if I'm collecting data from the temp sensor and using serial to do real-time plotting of temp vs time, but I want to be able to interrupt this at anytime to stop writing and switch to reading (saving data to .txt file). How could this be done?
Any help would be immensely appreciated.
Here is the Python code:
import serial
import time
import numpy as np
import matplotlib.pyplot as plt
ser = serial.Serial('/dev/tty.usbmodem1421', 9600, timeout = 5)
ser.flushInput()
ser.flushOutput()
time.sleep(0.1)
print ("Connected to serial port: {}".format(ser.name))
def Menu():
data_left = 1
while (data_left != 0):
print(ser.readline())
time.sleep(.1)
data_left = ser.inWaiting()
return
def RealTimePlot(y, count, k, minPlot, maxPlot):
//stuff
def WriteData(mode, plotData = 'n'):
//stuff
def ReadData(mode):
//stuff
def main():
launch = 0
plotData = ProgramIntro()
time.sleep(1)
Menu()
mode = raw_input("> ")
while (1):
if ((mode == "end") or (mode == 'exit')) :
ser.close()
exit()
elif (mode == 'm'):
ser.write(mode)
time.sleep(1)
Menu()
mode = raw_input("> ")
if (mode == 'm'):
print("Already at menu. Would you like to:")
print("[w]rite")
print("[r]ead")
print("[c]lear")
elif (mode == 'w'):
count = 0
WriteData(mode, plotData)
#mode = PauseProgram()
elif (mode == 'r'):
ReadData(mode)
#mode = PauseProgram()
elif (mode == 'c'):
ser.write(mode)
time.sleep(1)
while ser.inWaiting() > 0:
out = ser.readline()
print(out)
time.sleep(0.1)
mode = 'm'
print("Goodbye!")
#Closes the connection
ser.close()
And Arduino Code:
// References
// https://learn.sparkfun.com/tutorials/sik-experiment-guide-for-arduino---v32/experiment-7-reading-a-temperature-sensor
// https://www.arduino.cc/en/Tutorial/EEPROMWrite
// https://www.arduino.cc/en/Tutorial/EEPROMRead
//
// The following may be useful to read on storing EEPROM data:
// http://www.vernier.com/engineering/arduino/store-data-eeprom/
//
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <EEPROM.h>
// Define pins
const int writePin = 5;
const int readPin = 9;
const int pausePin = 7;
const int collectDataBtn = 11;
const int RTPin = 3;
const int sensorPin = A0; // Temperature Pin
char RTData;
int j = 0;
// SETUP of Serial port and PINS for LED
void setup() {
Serial.begin(9600);
pinMode(writePin, OUTPUT);
pinMode(RTPin, OUTPUT);
pinMode(readPin, OUTPUT);
pinMode(pausePin, OUTPUT);
pinMode(sensorPin, INPUT);
pinMode(collectDataBtn, INPUT);
while(Serial.available())
Serial.read();
}
char mode = 'm';
char prevMode = 'm';
int k = 0;
// MAIN LOOP
void loop() {
while (j == 0) {
if (k == 0) {
Serial.print("Would you like to plot real-time data? (y/n) ");
k++;
}
if (Serial.available() > 0) {
RTData = Serial.read();
if (RTData == 'y') {
digitalWrite(RTPin, HIGH);
j++;
}
else {
j++;
}
}
return;
}
switch (mode) {
// MENU mode
case 'm':
case 'M':
// Set LEDs to indicate menu mode
digitalWrite(writePin, HIGH);
digitalWrite(readPin, HIGH);
digitalWrite(pausePin, LOW);
// Print menu to serial port
PrintMenu();
while (mode == 'm') {
if (Serial.available() > 0) {
prevMode = mode;
mode = Serial.read();
}
}
break;
// WRITE mode
case 'w':
case 'W':
Serial.println("Entering WRITE mode...");
mode = WriteData(sensorPin, collectDataBtn);
break;
// READ mode
case 'r':
case 'R':
// Sets LEDs to indicate READ mode
digitalWrite(writePin, LOW);
digitalWrite(readPin, HIGH);
digitalWrite(pausePin, LOW);
Serial.println("Entering READ mode...");
mode = ReadData(sensorPin, prevMode);
break;
// CLEAR eeprom mode
case 'c':
case 'C':
Serial.println("Clearing EEPROM...");
ClearEEPROM();
Serial.println("EEPROM cleared!");
Serial.println("Returning to menu...\n\n");
mode = 'm';
break;
// PAUSE mode
default:
// Sets LEDs to indicate PAUSE mode
digitalWrite(writePin, LOW);
digitalWrite(readPin, LOW);
digitalWrite(pausePin, HIGH);
mode = 'p';
mode = PauseMode(mode);
break;
}
} // END void loop
void ClearEEPROM(void) {
for (int i = 0 ; i < EEPROM.length() ; i++) {
if ((i % 100 == 0) || (i % 50 == 0)) {
digitalWrite(writePin, HIGH);
digitalWrite(readPin, LOW);
digitalWrite(pausePin, LOW);
}
else {
digitalWrite(writePin, LOW);
digitalWrite(readPin, LOW);
digitalWrite(pausePin, HIGH);
}
EEPROM.write(i, 0);
}
return;
}
char CheckModeChange(void) {
if (Serial.available() > 0) {
// read the incoming char:
prevMode = mode;
mode = Serial.read();
}
return mode;
}
void PrintMenu(void) {
Serial.println("\n");
Serial.println(" ** Menu ** ");
Serial.println("------------------");
Serial.println("| [W]rite Data |");
Serial.println("| [R]ead Data |");
Serial.println("| [C]lear Data |");
Serial.println("------------------");
Serial.println("Enter [m]enu to return to menu at any point,");
Serial.println("or press any other key to pause during any point of the program.");
return;
}
char PauseMode(char mode){
Serial.println("Program Paused. Choose an option from the following to continue: ");
Serial.println("[m]enu");
Serial.println("[w]rite");
Serial.println("[r]ead");
Serial.println("[c]lear \n");
while (mode == 'p') {
if (Serial.available() > 0) {
mode = Serial.read();
}
}
return mode;
}
char WriteData(int sensorPin, int collectDataBtn) {
// Declarations
int cnt, voltVal;
int addr = 0; // Initializes address at 0 for EEPROM
int beginData = 0;
float voltage, degreesC;
char mode = 'w';
// Collect data when button pushed. This will be replaced by z-axis acceleration threshold
// of rocket.
Serial.println("Waiting for launch to begin...");
while (beginData == 0) {
if (cnt > 20000) {
cnt = 0;
}
else if (cnt < 10000) {
digitalWrite(writePin, LOW);
digitalWrite(readPin, LOW);
digitalWrite(pausePin, LOW);
}
else {
digitalWrite(writePin, HIGH);
digitalWrite(readPin, LOW);
digitalWrite(pausePin, LOW);
}
cnt++;
if (digitalRead(collectDataBtn) == HIGH) {
beginData = 1;
}
prevMode = mode;
mode = CheckModeChange();
if (prevMode != mode) {
beginData = 1;
}
}
digitalWrite(writePin, HIGH);
digitalWrite(readPin, LOW);
digitalWrite(pausePin, LOW);
// Write Data loop
while (mode == 'w') {
// First we'll measure the voltage at the analog pin. Normally
// we'd use analogRead(), which returns a number from 0 to 1023.
// Here we've written a function (further down) called
// getVoltage() that returns the true voltage (0 to 5 Volts)
// present on an analog input pin.
voltage = getVoltage(sensorPin);
// Now we'll convert the voltage to degrees Celsius.
// This formula comes from the temperature sensor datasheet:
// CONVERT IN PYTHON SCRIPT
// degreesC = (voltage - 0.5) * 100.0;
//Serial.print("Address[");
//Serial.print(addr);
//Serial.print("]: \t");
Serial.println(voltage);
/***
Write the value to the appropriate byte of the EEPROM.
these values will remain there when the board is
turned off.
***/
// Convert for storage to EEPROM
voltVal = (voltage * 10000) / 4;
// Write to EEPROM
EEPROM.write(addr, voltVal);
/***
Advance to the next address, when at the end restart at the beginning.
Larger AVR processors have larger EEPROM sizes, E.g:
- Arduno Duemilanove: 512b EEPROM storage.
- Arduino Uno: 1kb EEPROM storage.
- Arduino Mega: 4kb EEPROM storage.
Rather than hard-coding the length, you should use the pre-provided length function.
This will make your code portable to all AVR processors.
***/
addr = addr + 1;
/***
As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an
EEPROM address is also doable by a bitwise and of the length - 1.
++addr &= EEPROM.length() - 1;
***/
// Check for mode change
mode = CheckModeChange();
delay(100);
}
return mode;
}
char ReadData(int Pin, char prevMode) {
// Declarations
byte value;
float voltageVal, voltage, degreesC;
int addr = 0;
char mode = 'r';
// Checks previous mode. If previous mode was write, now that we are reading
// we should reset the EEPROM address to 0 so we can read from the beginning.
if ( (prevMode == 'w') || (prevMode == 'W') ) {
addr = 0;
}
while (mode == 'r') {
value = EEPROM.read(addr);
voltageVal = value;
voltage = voltageVal * 4 / 10000;
//Serial.print("Voltage: ");
//Serial.print("\t");
//Serial.println(voltage);
degreesC = (voltage - 0.5) * 100.0;
//Serial.print("Degrees C: ");
//Serial.print("\t");
//Serial.print("Address[");
//Serial.print(addr);
//Serial.print("]: \t");
Serial.println(degreesC);
/***
Advance to the next address, when at the end restart at the beginning.
Larger AVR processors have larger EEPROM sizes, E.g:
- Arduno Duemilanove: 512b EEPROM storage.
- Arduino Uno: 1kb EEPROM storage.
- Arduino Mega: 4kb EEPROM storage.
Rather than hard-coding the length, you should use the pre-provided length function.
This will make your code portable to all AVR processors.
***/
addr = addr + 1;
if (addr == EEPROM.length()) {
addr = 0;
}
// Check for mode change
mode = CheckModeChange();
delay(100);
}
return mode;
}
float getVoltage(int pin) {
// This function has one input parameter, the analog pin number
// to read. You might notice that this function does not have
// "void" in front of it; this is because it returns a floating-
// point value, which is the true voltage on that pin (0 to 5V).
return (analogRead(pin) * 0.004882814);
// This equation converts the 0 to 1023 value that analogRead()
// returns, into a 0.0 to 5.0 value that is the true voltage
// being read at that pin.
}
Related
I am trying to get my firebase data and display it to my 7-segment using Arduino and I am getting the help of a python script to send data to the serial monitor. While it detects the Serial.available() inside the loop but I don't know how could I get that particular value and display its first digit to my 7-segment
Currently for the test I am just trying to display 1 if there is data matches inside serial monitor and arduino
Adruino:
#define A PA0
#define B PA1
#define C PA2
#define D PA3
#define E PA4
#define F PA5
#define G PA6
int a = 2;
void setup() {
Serial.begin(9600);
pinMode(A, OUTPUT);
pinMode(B, OUTPUT);
pinMode(C, OUTPUT);
pinMode(D, OUTPUT);
pinMode(E, OUTPUT);
pinMode(F, OUTPUT);
pinMode(G, OUTPUT);
}
void loop() {
if(Serial.available()){
// Serial.println("0 1 2 3 4 5 6 7 8 9");
// sevenSeg(1, 1, 1, 1, 1, 1, 0); // 0
// delay(500);
if(Serial.readString() == Serial.readString()){
sevenSeg(0, 0, 0, 1, 1, 0, 0); // 1
delay(500);
}
}else{
sevenSeg(1, 1, 1, 1, 1, 1, 0);
}// 0
}
void sevenSeg (int g, int f, int e, int d, int c, int b, int a)
{
digitalWrite(A, a);
digitalWrite(B, b);
digitalWrite(C, c);
digitalWrite(D, d);
digitalWrite(E, e);
digitalWrite(F, f);
digitalWrite(G, g);
}
Python Script:
import pyrebase
import argparse
import datetime
import time
import math
import serial
from serial import Serial
time_str = datetime.datetime.now().strftime("%Y%b%d_%I:%M:%S%p").upper()
ap = argparse.ArgumentParser()
ap.add_argument("-t", "--temp", help="Patient temperature at time of reading") #
ap.add_argument("-r", "--heart", help="Patient heart rate at the time of reading")
args = vars(ap.parse_args())
#firebase configuration
firebaseConfig = {
"apiKey": "",
"authDomain": "heartrate-firebase.firebaseapp.com",
"databaseURL": "https://heartrate-firebase-default-rtdb.firebaseio.com/",
"projectId": "heartrate-firebase",
"storageBucket": "heartrate-firebase.appspot.com",
"messagingSenderId": "851991577466",
"appId": "1:851991577466:web:daaf323d9af64fd3318cc3",
}
firebase = pyrebase.initialize_app(firebaseConfig)
db = firebase.database()
if args.get("temp", None) is not None:
data = {"Temperature": args.get("temp", None)}
db.child("Temperature").child(time_str).set(data)
if args.get("heart", None) is not None:
data = {"HeartRate": args.get("heart", None)}
db.child("HeartRate").child(time_str).set(data)
user = db.child("HeartRate").get()
for x in user.each():
date = db.child("HeartRate").child(x.key()).child("HeartRate").get()
print("Heart Rate: " + date.val())
userTemp = db.child("Temperature").get()
for x in userTemp.each():
date = db.child("Temperature").child(x.key()).child("Temperature").get()
# date = db.child("Temperature").get()
print("Temperature: " + date.val())
with serial.Serial('COM4', 9600, timeout=5) as ser:
time.sleep(2)
ser.write((date.val() + '\n').encode())
time.sleep(1)
y = ser.read(ser.inWaiting())
print(y)
# ser.close()
All I end up with is displaying 0. Any help or ideas are greatly appreciated. Thanks.
the problem was I was receiving 2\r\n from the database so to remove \r\n I used strip() to remove \r\n and it worked.
I am trying to make a resource monitor with an arduino and it is working great for almost 20 seconds before it almost stops running.
When it slows down, it takes almost 5 seconds between updates.
I have tried to comment out everything with psutil and giving it a permanent value.
and have tried the same with GPUtil.
Here is the python code
import serial.tools.list_ports
import serial
import psutil
import GPUtil
import time
import serial
ports = list(serial.tools.list_ports.comports())
baud = 9600
for p in ports:
if "Arduino" in p[1]:
port = p[0]
ser=serial.Serial(port, baud, timeout=1)
try:
while True:
cpuUsage = psutil.cpu_percent()
ramUsage = psutil.virtual_memory()
cpuUsage = str(cpuUsage)
GPUs = GPUtil.getGPUs()
gpuUsage = GPUs[0].load
gpuUsage = str(gpuUsage)
gpuUsage = gpuUsage[2:]
ramUsage = str(ramUsage.percent)
toSend = cpuUsage + "," + gpuUsage + ","+ ramUsage
print (toSend)
ser.write(toSend.encode())
#print("20.5".encode())
#line = ser.readline()[:-2]
#line.decode()
#print ("Read : " , line);
time.sleep(0.1)
except:
print ("error")
Here is the Arduino code
#include <FastLED.h>
#define NUM_LEDS 15
#define DATA_PIN 6
float Cpu = 40;
float Gpu = 99;
float Ram = 60;
String Cpu_Read;
String Gpu_Read;
String Ram_Read;
int RXLED = 17;
String StrNumbers = "";
int numbers;
int Received = 0;
int Separrator = 0;
String Text = "";
CRGB leds[NUM_LEDS];
void setup() {
// put your setup code here, to run once:
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(5);
Serial.begin(115200);
pinMode(LED_BUILTIN_TX,INPUT);
pinMode(LED_BUILTIN_RX,INPUT);
}
void loop() {
// put your main code here, to run repeatedly:
char inByte = ' ';
StrNumbers = "";
Text = "";
Separrator = 0;
Cpu_Read = "";
Gpu_Read = "";
Ram_Read = "";
Received = 0;
pinMode(LED_BUILTIN_TX,INPUT);
while(Serial.available() > 0){ // only send data back if data has been sent
pinMode(LED_BUILTIN_TX,OUTPUT);
inByte = Serial.read(); // read the incoming data
if (inByte == ','){
Separrator += 1;
}
else if (Separrator == 0){
Cpu_Read += (char) inByte;
}
else if (Separrator == 1){
Gpu_Read += (char) inByte;
}
else if (Separrator == 2){
Ram_Read += (char) inByte;
Serial.print("Ram : ");
Serial.println(Ram_Read);
}
else{
Serial.println("Error");
}
/*
inByte = Serial.read(); // read the incoming data
if (isDigit(inByte)) { // tests if inByte is a digit
StrNumbers += (char) inByte;
Serial.println(inByte); // send the data back in a new line so that it is not all one long line
//Serial.println(numbers); // send the data back in a new line so that it is not all one long line
}
else if (inByte == ".")
{
abortLoop = 1;
}
else{
Text +=(char) inByte;
}
*/
Received = 1;
}
if (Received == 1){
Cpu = Cpu_Read.toInt();
Gpu = Gpu_Read.toInt();
Ram = Ram_Read.toInt();
UpdateMonitor(Cpu ,Gpu ,Ram);
}
Text.trim();
if (StrNumbers != ""){
numbers = StrNumbers.toInt();
Serial.println(numbers);
if (numbers > 100) numbers = 100;
UpdateMonitor(Cpu,numbers,Ram);
}
if(Text!= ""){
//Serial.println(Text); // send the data back in a new line so that it is not all one long line
}
if (Text == "ResourceMonitor"){
Serial.println("Yes");
}
else if (Text != ""){
Serial.println(Text);
numbers = Text.toInt();
if (numbers > 100) numbers = 100;
UpdateMonitor(Cpu, numbers, Ram);
}
}
void UpdateMonitor(int cpu,int gpu, int ram){
int Cpu_Usage = map(cpu, 0, 100, 0, 5);
int Gpu_Usage = map(gpu, 0, 100, 0, 5);
int Ram_Usage = map(ram, 0, 100, 0, 5);
FastLED.clear();
for(int led = 0; led < Ram_Usage; led++) {
leds[led] = CRGB::Blue;
}
for(int led = 0; led < Gpu_Usage; led++) {
leds[9 - led] = CRGB::Green;
}
for(int led = 0; led < Cpu_Usage; led++) {
leds[led+10] = CRGB::Red;
}
FastLED.show();
}
it is fixed now not sure what fixet it but it works atleast :)
thansk to all that have tried to helt
I got a system where I would send a command from my host computer using Python Socket (the computer is the server) and the MKR1000 (client) would send back information depends on the command sent.
Unfortunately, the bidirectional communication is unstable. I can guarantee the MKR1000 received the command and (maybe) sending information back, but for some reason, my host computer would not receive the command.
Anyway, this is my first time trying out socket, so I would like some guru to review my code and maybe spot the mistake in here? Thanks a lot.
Python:
import socket
import time
def coor2bytes(coor_fnc):
coorByte = [0, 0, 0, 0, 0, 0]
if (coor_fnc[0] >= 0):
coorByte[0] = (coor_fnc[0] >> 8) & 0xFF # High byte of X
coorByte[1] = coor_fnc[0] & 0xFF # Low byte of X
else:
coor_fnc[0] = coor_fnc[0]*(-1)
coorByte[0] = (coor_fnc[0] >> 8) & 0xFF # High byte of X
coorByte[0] = coorByte[0] ^ 0x80
coorByte[1] = coor_fnc[0] & 0xFF # Low byte of X
if (coor_fnc[1] >= 0):
coorByte[2] = (coor_fnc[1] >> 8) & 0xFF # High byte of Y
coorByte[3] = coor_fnc[1] & 0xFF # Low byte of Y
else:
coor_fnc[1] = coor_fnc[1]*(-1)
coorByte[2] = (coor_fnc[1] >> 8) & 0xFF # High byte of X
coorByte[2] = coorByte[2] ^ 0x80
coorByte[3] = coor_fnc[1] & 0xFF # Low byte of X
if (coor_fnc[2] >= 0):
coorByte[4] = (coor_fnc[2] >> 8) & 0xFF # High byte of Phi
coorByte[5] = coor_fnc[2] & 0xFF # Low byte of Phi
else:
coor_fnc[2] = coor_fnc[2]*(-1)
coorByte[4] = (coor_fnc[2] >> 8) & 0xFF # High byte of Phi
coorByte[4] = coorByte[4] ^ 0x80
coorByte[5] = coor_fnc[2] & 0xFF # Low byte of Phi
return coorByte
def bytes2coor(byte_fnc):
receivedCoor_fnc = [0, 0, 0]
receivedCoor_fnc[0] = ((-1)**(byte_fnc[0]>>7)) * ((byte_fnc[1]) | (((byte_fnc[0]&0x7f)<<8)))
receivedCoor_fnc[1] = ((-1)**(byte_fnc[2]>>7)) * ((byte_fnc[3]) | (((byte_fnc[2]&0x7f)<<8)))
receivedCoor_fnc[2] = ((-1)**(byte_fnc[4]>>7)) * ((byte_fnc[5]) | (((byte_fnc[4]&0x7f)<<8)))
return receivedCoor_fnc
if __name__ == '__main__':
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 1234)) # bind(ip, port)
print("Done binding.")
s.listen(2)
clientsocket, address = s.accept()
print(f"Connection from {address} has been established!")
clientsocket.settimeout(1)
while True:
print();
print("What you want to do?")
print("0. Send target")
print("1. Get current coordinate")
print("2. Set current coordinate (not yet implement)")
try:
a = int(input("I choose: "))
except Exception:
print("Error.")
a = -1;
if (a == 0):
coor = [0, 0, 0]
try:
coor[0] = int(input("X: "))
coor[1] = -int(input("y: "))
coor[2] = int(input("phi: "))
coorByte = coor2bytes(coor)
clientsocket.send(bytes([0]))
clientsocket.send(bytes(coorByte))
print("I already sent the target.")
except Exception:
print("Error.")
elif (a == 1):
receive = 0
while (not receive):
try:
clientsocket.send(bytes([1]))
bytesReceived = []
full_msg = []
while (len(full_msg) < 8):
bytesReceived = clientsocket.recv(8)
for x in range(len(bytesReceived)):
full_msg.append(bytesReceived[x])
receivedCoor = bytes2coor(full_msg)
print("coordinate received: " + str(receivedCoor))
receive = 1
except socket.timeout:
print("Time out. Will try again.")
elif (a == 2):
setCoor = [0, 0, 0]
try:
setCoor[0] = int(input("X: "))
setCoor[1] = -int(input("y: "))
setCoor[2] = int(input("phi: "))
setcoorByte = coor2bytes(setCoor)
clientsocket.send(bytes([2]))
clientsocket.send(bytes(setcoorByte))
print("I already sent the new coordinate.")
except Exception:
print("Error.")
else:
print("Not yet implement.")
Arduino:
#include <WiFi101.h>
#include <SPI.h>
// To connect to the server on laptop
char ssid[] = "iPhone";
char pass[] = "00000000";
int status = WL_IDLE_STATUS;
IPAddress server(172,20,10,3);
WiFiClient client;
// Random variable
int a, i, j, k, m;
byte buf0[7];
byte buf1[7];
byte buf2[7];
long start = millis();
int elapsedTime = 0;
int timeout = 0;
void setup() {
// put your setup code here, to run once:
// Serial.begin(115200);
Serial.begin(115200);
Serial1.begin(115200);
// status = WiFi.begin(ssid, pass);
while (status != WL_CONNECTED) {
status = WiFi.begin(ssid, pass);
}
j = client.connect(server, 1234);
while (j != 1) {
j = client.connect(server, 1234);
}
}
void loop()
{
if (client.available()) {
a = client.read();
Serial.print("I got: ");
Serial.println(a);
if (a == 0) { // Send new target to Due
Serial.println("I send target.");
j = 0;
start = millis();
while(j<6) {
elapsedTime = millis() - start;
if (elapsedTime > 1000) {
timeout = 1;
break;
}
if (client.available()>0) {
buf0[j] = client.read();
Serial.println(buf0[j]);
j++;
}
}
if (timeout != 1) {
Serial1.write((byte) 0);
// Send coordinate back to Due
for (i = 0; i<6; i++) {
Serial1.write(buf0[i]);
}
} else {
timeout = 0;
}
} else if (a == 1) {
// Get the coordinate from the Due
Serial.println("I receive coordinate.");
Serial1.write((byte) 1);
k = 0;
start = millis();
while(k < 6) {
elapsedTime = millis() - start;
if (elapsedTime > 1000) {
timeout = 1;
break;
}
if (Serial1.available() > 0) {
buf1[k] = Serial1.read();
Serial.println(buf1[k]);
k++;
}
}
if (timeout != 1) {
for (i=0;i<6;i++) {
client.write(buf1[i]);
delay(10);
}
client.write((byte) 0); // fill in the blank size
delay(10);
client.write((byte) 0);
} else {
timeout = 0;
}
// for (int i = 0; i<8; i++) {
// client.write((byte) 0);
// }
} else if (a == 2) { // set the current coordinnate to be something else.
Serial.println("I set coordinate.");
m = 0;
while(m<6) {
if (client.available()>0) {
buf2[m] = client.read();
Serial.println(buf2[m]);
m++;
}
}
Serial1.write((byte) 2);
// Send coordinate back to Due
for (i = 0; i<6; i++) {
Serial1.write(buf2[i]);
}
} else if (a == 3) { // identify yourself
Serial.println("Identify myself.");
client.write((byte) 1);
}
}
}
If you have time to read through the Arduino code, then you would see that I actually have serial communication between my MKR and Due too. I also can guarantee that the MKR can receive all those data from the Due and not stuck in some infinite loop.
Thank you!
Ok so for some reason if I added a delay right after the MKR connecting to WiFi, before connecting to the server, then everything just works.
I am trying to communicate via my laptop to my arduino using the USB serial port. I am using Python 3.6, with the serial package. The simplified version of my Python code is :
import serial
import time
with serial.Serial(port="COM3", baudrate=9600) as ser:
time.sleep(2)
while True:
x, y, angle = detectAndDisplay(frame, face_cascade, eyes_cascade)
if x is not None:
ser.write((str(x * 100 // 177) + "/n").encode())
ser.write((str(y * 100 // 133) + "/n").encode())
if cv.waitKey(10) == 27:
break
Where the function detectAndDisplay() returns three int values. The values x, y are scaled to be between 0 and 180. I want to send the values x, y to the arduino, which has the following simplified code:
#include <PID_v1.h>
#include <Servo.h>
Servo Servo_1;
Servo Servo_2;
double Setpoint_1 = 90;
double Input_1;
double Output_1;
double Setpoint_2 = 90;
double Input_2;
double Output_2;
double Kp_1 = 0.022;
double Ki_1 = 0.012;
double Kd_1 = 0;
double Kp_2 = 0.032;
double Ki_2 = 0.022;
double Kd_2 = 0;
PID PID1(&Input_1, &Output_1, &Setpoint_1, Kp_1, Ki_1, Kd_1, DIRECT);
PID PID2(&Input_2, &Output_2, &Setpoint_2, Kp_2, Ki_2, Kd_2, DIRECT);
int serialCount = 0;
int serialInArray[2];
int posX = 90;
int posY = 90;
int errorX;
int errorY;
void setup() {
Serial.begin(9600);
Servo_1.attach(32);
Servo_2.attach(34);
PID1.SetMode(AUTOMATIC);
PID1.SetSampleTime(1);
PID1.SetOutputLimits(-35, 35);
PID2.SetMode(AUTOMATIC);
PID2.SetSampleTime(1);
PID2.SetOutputLimits(-35, 35);
Servo_1.write(90);
Servo_2.write(90);
}
void loop() {
while(Serial.available() == 0);
serialInArray[serialCount] = (Serial.read());
serialCount++;
if (serialCount > 1){
Input_1 = serialInArray[1];
Input_2 = serialInArray[0];
PID1.Compute();
PID2.Compute();
posX = posX + Output_2;
posY = posY + Output_1;
Servo_1.write(posX);
Servo_2.write(posY);
serialCount = 0;
}
}
Where I will use the values of posX and posY as input for servo motors. However, what I notice is that input is received on the arduino because it starts doing something as soon as the python script is started. However, the servo motors start turning to zero as soon as the input is received. This behavior is independent of the value that I am sending. What am I missing or what am I doing wrong?
I would like to trigger data acquisition on my Arduino UNO with connected accelerometer (MPU 6050) by using Python.
The idea is that when the command is given in Python, the Arduino would start saving data on its SRAM and when a certain number of measurements would be saved, the data would be sent in a package back to Python.
This is my current Arduino code:
#include<Wire.h>
#define MPU6050_DLPF_94HZ MPU6050_DLPF_CFG_2
const int MPU_addr_1 = 0x68; // I2C address of the first MPU-6050
const int baudrate = 19200;
int16_t AcX1; // definition of variables
const int len = 200; // Buffer size
float analogDataArray[len];
int count = 0;
void setup() {
Wire.begin();
Wire.beginTransmission(MPU_addr_1);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
Serial.begin(baudrate);
}
void loop() {
Wire.beginTransmission(MPU_addr_1);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr_1, 8, true); // request a total of 14 registers
float AcX1 = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
if (Serial.available())
{
if (Serial.read() == 'Y') {
analogDataArray[count] = AcX1;
count = count + 1;
if (count >= len) {
for (int i; i <= len; i = i + 1) {
Serial.println(analogDataArray[i] / 16384);
}
}
count = 0;
}
}
delay(5);
}
and this is my Python code:
import serial
arduinoData = serial.Serial('COM3', 19200)
com = input('Press "Y":' )
arduinoData.write(bytes(com, 'utf-8'))
vec = []
run = True
while run is True:
while (arduinoData.inWaiting() == 0):
pass
arduinoString = arduinoData.readline()
vec.append(float(arduinoString))
if len(vec) >= 100:
run = False
print(vec)
I've managed to get it working for 1 measurement but as soon as I defined an array inside Arduino to save multiple measurements, the code doesn't work. I'm sure that it is close to working, but I can't find the detail that is stopping me from that.
Thank you for any provided help.
Kind regards,
L
I got it working, the problem was in my Arduino code, as expected.
#include<Wire.h>
#define MPU6050_DLPF_94HZ MPU6050_DLPF_CFG_2
const int MPU_addr_1 = 0x68; // I2C address of the first MPU-6050
const int baudrate = 9600;
int16_t AcX1; // definition of variables
const int len = 200; // Buffer size
float analogDataArray[len];
int count = 0;
int ans;
void setup() {
Wire.begin();
Wire.beginTransmission(MPU_addr_1);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
Serial.begin(baudrate);
}
void loop() {
Wire.beginTransmission(MPU_addr_1);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr_1, 8, true); // request a total of 14 registers
float AcX1 = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
if (Serial.available() && Serial.read() == 'Y') {
ans = 1;
}
if (ans == 1) {
analogDataArray[count] = AcX1;
count = count + 1;
if (count >= len) {
for (int i; i <= len; i = i + 1) {
Serial.println(analogDataArray[i] / 16384);
}
ans = 0;
}
}
delay(5);
}