I'm have written some code for the Arduino, where it receives a value from a python script over serial. It's then supposed to compare this value to a running total of encoder pulses, when the encoder pulses exceed this value the motors should stop running. I'm yet to integrate them motor part, that's the next step. I'm having an issue where the Arduino reaches the comparison while loop, in this loop I have it printing some information to the serial monitor for debugging - the issue is it only prints 4 or 5 lines before the output stops and the information it outputs is strangely formatted.
I have no idea what I'm doing wrong.
#include <Arduino.h>
#include <math.h>
#define ENC_COUNT_REV 64
#define GEAR 60 //30:1 + 2:1 gear ratio
#define ENC_PIN_A 20
#define ENC_PIN_B 21
#define ARD_PI_PIN 18
// MOTOR WIRING DATA
// Red - pos
// Black - Neg
// Green - GND
// Blue - Vcc (3.3v-20v)
// Yellow - Output A
// White - Output B
// Encoder counters
volatile long enc_a_count = 0;
volatile long enc_b_count = 0;
volatile long encoderCount = 0;
volatile long count;
unsigned long reqCounts = 0;
unsigned long copy_count = 0;
void setup() {
Serial.begin(115200);
Serial.setTimeout(1);
pinMode(ENC_PIN_A, INPUT_PULLUP);
pinMode(ENC_PIN_B, INPUT_PULLUP);
//attachInterrupt(digitalPinToInterrupt(ARD_ABORT_PIN), abort, RISING);
attachInterrupt(digitalPinToInterrupt(ENC_PIN_A), updateEncoderA, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENC_PIN_B), updateEncoderB, CHANGE);
}
void loop() {
String data = "";
while (true) {
while (!Serial.available());
data = Serial.readStringUntil('\n');
if (data == "OK") {
break; // Break out of the loop if "OK" is received
} else {
reqCounts = strtoul(data.c_str(), NULL, 10);
Serial.print(reqCounts);
delay(5);
}
}
// LOWER SENSOR CODE TO GO HERE
while (true) {
Serial.print(" Running Total pulses:");
Serial.print(copy_count);
Serial.print('\t');
Serial.print(" Target pulses:");
Serial.print(reqCounts);
Serial.println();
delay(5);
noInterrupts();
copy_count = count;
interrupts();
if (copy_count <=0.5*reqCounts) {
//Set PIN to High
}
if (copy_count >=0.5*reqCounts) {
//Set PIN to Low
}
if (copy_count >= 0.9*reqCounts) {
// Set PIN to High
}
if (copy_count >= reqCounts) {
// Set PIN to Low (STOP MOTORS)
reqCounts = 0;
copy_count = 0;
count = 0;
break;
}
}
// RAISE SENSOR CODE TO GO HERE
}
void updateEncoderA() {
count++;
enc_a_count++;
}
void updateEncoderB() {
enc_b_count++;
count++;
}
Heres an example of the serial monitor output (mind you it changes every time the codes run):
20:49:39.384 -> Running R
20:49:39.384 -> Runniotal pulses:0 Target pulses:200
20:49:39.384 -> Running Total pulses:0 Target pulses:200
20:49:39.384 -> Running Total pulses:0 Target pulses:200
20:49:39.384 -> Running Total pulses0 T
simple schematic; include power arrangements, what's generating the interrupt, how fast, etc., what motor control arrangement.
When you don't know what the problem is, don't assume "it isn't ..." and therefore limit what you share with us - because you don't know what you don't know. Yes, some sharing may result in 'critique' or 'helpful advice'. That's part of resolving the issue.
There really isn't much more too it. I'm using an arduino mega 2560, but have also attempted to run the script on a nano (no success).
I plan on using pololu 37d geared motors which have a built in encoder. I haven't bothered wiring them up yet, I can't see any point if the serial print can't even relay information from the encoder. So the wiring schematic is a serial connection with my laptop over USB-B. I will share the script I'm running on my laptop when Im home.
I ran your code with nothing attached to an UNO. I type 177 <return> followed by OK <return> and this printed, very rapidly and would have forever.
177 Running Total pulses:0 Target pulses:177
Running Total pulses:0 Target pulses:177
Running Total pulses:0 Target pulses:177
Running Total pulses:0 Target pulses:177
Running Total pulses:0 Target pulses:177
So I have no clue why it is not the same over where you are at.
With a rotary attached encoder, either direction adds to a count that reaches for the Target at which point the hole mess seems to reset (wait for target number + OK entry).
I have managed to recreate your results by sending to the serial monitor rather than from the python script. Seems to suggest its an issue with the python script right?
Here is the code I'm running on Python:
import serial
import time
counts = 200
def serial_comm(count):
ser = serial.Serial('COM3', 115200, timeout=1)
time.sleep(5)
ser.reset_input_buffer()
ser.write(bytes(str(count) + '\n', 'utf-8'))
time.sleep(1)
received_data = ser.readline().decode('utf-8').strip()
if received_data != str(count):
print(f"Received data {received_data} does not match the expected count {count}. Retrying...")
ser.close()
serial_comm(count) # Recursive call to send and verify again
else:
ser.write(bytes('OK\n', 'utf-8'))
print("Data sent OK")
ser.close()
serial_comm(counts)
How would you propose doing this? Using the UNO as an intermediary or is there a special USB cable you can buy which can be plugged directly into the I/O pins on the Arduino?
That's a good idea. I didn't make much of the Python code.
Another thing you could try is using a serial terminal program instead of Python, just for testing.
Leave the Arduino serial monitor window closed, and after you uplaod you code, hook up to the Arduino using the same port on your PC through either PuTTY or CoolTerm, both just terminal emulators.