0

I have a camera tracking ARUCO markers on a conveyor belt. The camera spots a marker & sends a byte via serial (USB) to a Nano that's, controlling a L298N H-Bridge to change the direction of the motor driving the conveyor.

The snippet of Python on the Camera PC side. The method reads an image, looks for markers. if its number 5 & this wasn't seen last time then 40 is sent to the Nano, the same if it sees marker 23. Each time I wait for an acknowledge byte @ from the Nano as a sanity check that the byte has been sent.

def find_aruco(self):
        
    im = cv2.imread('image.png')
    im_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    corners, aruco_ids, rejects = aruco.detectMarkers(im_gray, self.aruco_dict, parameters=self.aruco_params)

    if aruco_ids is not None: 
            
        aruco_ids_flat = aruco_ids.flatten()
        print('detected: ', aruco_ids_flat)
            
        if aruco_ids_flat[0] == 5 and self.belt_direction:
                
            self.ser.write(struct.pack('>B', 40))
            self.belt_direction = False
            print(aruco_ids_flat[0], self.belt_direction)
            ack = self.ser.read(1)
            self.ser.flushInput()
            print(ack)
                
        if aruco_ids_flat[0] == 23 and not self.belt_direction:
                
            self.ser.write(struct.pack('>B', 40))
            self.belt_direction = True
            print(aruco_ids_flat[0], self.belt_direction)
            ack = self.ser.read(1)
            self.ser.flushInput()
            print(ack)
                
        os.remove("image.png")
        return False

        else:
            print("---")
            os.remove("image.png")
            return False

On the Nano side I have,

#define enA 6
#define in1 7
#define in2 8

bool in_1 = LOW;
bool in_2 = HIGH;

int ser_pwm = 0;

void setup() {

  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);

  digitalWrite(in1, in_1);
  digitalWrite(in2, in_2);
  analogWrite(enA, 0);

  Serial.begin(9600);
}


void loop() {

  if (Serial.available() > 0) {
    ser_pwm = Serial.read();
  }
  
  if (ser_pwm == 40){

    digitalWrite(in1, !digitalRead(in1)); // change direction by inverting pins
    digitalWrite(in2, !digitalRead(in2));
    Serial.print("@");

  }else{
     analogWrite(enA, ser_pwm); 
  }
  
}

ser_pwm is set outside of the ARUCO detector method & set to 0 whilst detection is happening then to 100 once the the method has finished.

OK so the output I'm getting on the PC is what I expect

detected:  [5 5 5 5]
5 False
b'@'
detected:  [23 23 23]
23 True
b'@'
detected:  [5 5 5 5]
5 False
b'@'
detected:  [23 23]
23 True
b'@'
detected:  [23 23 23 23]
detected:  [23 23]
detected:  [5 5 5 5]
5 False
b'@'
detected:  [5 5 5 5]
All closed.
User interrupt: Exiting...

But what I'm not expecting is that even though the Nano is acknowledging is has received the change direction byte, it doesn't always change the direction. I've checked connections but nothing loose. Have rewired it twice still the same erratic behaviour, sometimes it'll change direction sometime not but will always send the acknowledgement that it has.

My next step to to swap out the Nano then swap out the motor board but I'm asking here if anyone can see something that I'm too close to see in the code?

EDIT :: I added Serial.flush() at the end of the main loop but this hasn't changed the behaviour.

EDIT :: Changed refactored the logic just to depend on one Boolean. Its made no difference to the behaviour.

if (ser_pwm == 40){
    in_1 = !in_1;
    Serial.print("@");
  }else{
    digitalWrite(in1, in_1);
    digitalWrite(in2, !in_1);
    analogWrite(enA, ser_pwm); 
  }

EDIT :: I have swapped out all the components, connectors, Nano, motor board, one by one..... still the same intermittent behaviour.

7
  • invert in_1 not the pin reading ... you don't need in_2, it's redundant in your code
    – jsotola
    Apr 19 at 15:26
  • @jsotola pretty sure I do, otherwise the current through the H bridge wont have a path through the motor.
    – DrBwts
    Apr 19 at 15:37
  • the two pins are always opposite to each other, therefore you need only one variable to track their state
    – jsotola
    Apr 19 at 15:43
  • @jsotola I get you, I refactored as suggested (see edit to OP). The behaviour remains unchanged.
    – DrBwts
    Apr 19 at 15:50
  • 1
    something is mis-wired
    – jsotola
    Apr 19 at 16:22

1 Answer 1

0

It was a serial comms timing issue. The main() loop was cycling faster than the serial buffer was updating so the direction was being changed faster than the PC side image acquisition was working, leading to erratic behaviour.

I put a delay in the change direction block, 250ms worked here,

 if (ser_pwm == 40){

    digitalWrite(in1, !digitalRead(in1)); // change direction by inverting pins
    digitalWrite(in2, !digitalRead(in2));
    Serial.print("@");
    delay(250);                           // added delay to ensure the PC acq is upto speed
  }else{
     analogWrite(enA, ser_pwm); 
  }

Interestingly Serial.flush() doesn't appear to flush the input buffer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.