Hello everyone!
Currently, I'm working on the project of a line tracking robot using a PC as an image processing unit. I wrote code in Python using the OpenCV package and in C++ for Arduino Uno. Both are provided below.
They are talking through the serial port.
The problem is that: when python sends data several times per second robot does not process this data. But when I starting the second thread in python and sending data only 1 time in a second it works. I tried higher baud rates but it also fails to decrease this time.
Can anybody help with this?
Code for Arduino Uno
int value;
int absoluteVal;
int derVal;
int in1 = 7;
int in2 = 6;
int in3 = 5;
int in4 = 4;
int ena = 9;
int enb = 3;
void setup() {
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
pinMode(ena, OUTPUT);
pinMode(enb, OUTPUT);
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
digitalWrite(ena, LOW);
digitalWrite(enb, LOW);
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
value = Serial.parseInt();
if (value == 10) {
analogWrite(ena, 70);
analogWrite(enb, 0);
}
else if (value == 20) {
analogWrite(ena, 70);
analogWrite(enb, 25);
}
else if (value == 30) {
analogWrite(ena, 70);
analogWrite(enb, 50);
}
else if (value == 40) {
analogWrite(ena, 70);
analogWrite(enb, 70);
}
else if (value == 50) {
analogWrite(ena, 50);
analogWrite(enb, 70);
}
else if (value == 60) {
analogWrite(ena, 25);
analogWrite(enb, 70);
}
else if (value == 70) {
analogWrite(ena, 0);
analogWrite(enb, 70);
}
else {
analogWrite(ena, 0);
analogWrite(enb, 0);
}
}
}
Code for Python:
import imutils
import numpy as np
import cv2
import serial
import threading
import time
flag = 0
lastTime = 0
global D
global thread1
class myThread (threading.Thread):
def __init__(self, distance):
threading.Thread.__init__(self)
self.distance = distance
def run(self):
send_data(self.distance)
def send_data(data):
global lastTime
millis = int(round(time.time()*1000))
if millis-lastTime>=500:
if (data > 100):
d = 70
print("Turn right: ", D)
ser.write(str(d).encode())
elif (abs(data) < 100 and abs(data) > 0):
d = 40
print("Straight", abs(D))
ser.write(str(d).encode())
elif (data < -100):
d = 10
print("Turn left: ", D)
ser.write(str(d).encode())
elif(data == 0):
d = 0
print("Stop")
ser.write(str(d).encode())
lastTime = millis
ser = serial.Serial(
port='\\\\.\\COM10',
baudrate=9600,
parity=serial.PARITY_ODD,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
)
cap = cv2.VideoCapture(1)
while True:
D = 0
_, frame = cap.read()
blurred = cv2.GaussianBlur(frame, (5, 5), 0)
hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)
part_1 = hsv[140:240, 0:640]
part = frame[140:240, 0:640]
lower_b = np.array([0, 60, 118])
upper_b = np.array([179, 255, 221])
mask = cv2.inRange(part_1, lower_b, upper_b)
# find contours in the mask image
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
# loop over the contours
for c in cnts:
# compute the center of the contour
M = cv2.moments(c)
if M["m00"] != 0:
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
else:
cX, cY = 0, 0
# draw the contour and center of the shape on the image
area = cv2.contourArea(c)
if (area > 5000):
cv2.drawContours(part, [c], 0, (0, 255, 0), 2)
cv2.circle(part, (cX, 60), 7, (255, 255, 255), -1)
D = (320 - cX)
else:
D = 0
thread1 = myThread(D)
thread1.start()
cv2.circle(part, (320, 60), 7, (0, 0, 255), -1)
cv2.imshow("frame", frame)
key = cv2.waitKey(10) & 0xFF
if key == ord("q"):
break
cap.release()
cv2.destroyAllWindows()