1

R Pi 3 B+, Arduino Mega 2650

I am trying to send motor control instructions via user input from the Pi to the Mega.

Pi side code...

import serial

port = "/dev/ttyACM0"
rate = 9600
s1 = serial.Serial(port, rate)
s1.flushInput()

def motors_over_serial(left_1, left_2, right_1, right_2, pwm):

    directions = left_1 + left_2 + right_1 + right_2
    print(directions)
    directions = int(directions, 2)
    print(directions)
    s1.write(str.encode(str(directions)))
    s1.write(str.encode(pwm))

while True:

    left_1  = input("left 1: ")
    left_2  = input("left 2: ")
    right_1 = input("right 1: ")
    right_2 = input("right 2: ")
    pwm     = input("pwm %: ")


    motors_over_serial(left_1, left_2, right_1, right_2, pwm)

    print("----------------")

Where left_1, Left_2 etc are single binary digits that set up the h-bridge direction control & pwm is the pwm duty cycle.

On the Mega side...

// Outputs to H bridges
// h_bridge_pwm_left  = 8  
// h_bridge_left_1    = 9  
// h_bridge_left_2    = 10 
// h_bridge_pwm_right = 11 
// h_bridge_right_1   = 12 
// h_bridge_right_2   = 13 
int h_bridge_outputs[] = {8, 9, 10, 11, 12, 13};
const int num_outputs = sizeof(h_bridge_outputs) / sizeof(h_bridge_outputs[0]);

// Inputs from Pi
int from_r_pi_pwm = 0;
int from_r_pi_dir = 0;
int pwm;

void setup() {

  Serial.begin(9600);

  // Outputs to H bridge
  for (int i = 0; i < num_outputs; i++)
  {
    pinMode(h_bridge_outputs[i], OUTPUT);
    digitalWrite(h_bridge_outputs[i], LOW);
  }
}

void loop() {

  // Check input from R Pi & send it to the H bridges
  while (!Serial.available()){}

  if (Serial.available()) {
    from_r_pi_dir = Serial.parseInt();
    from_r_pi_pwm = Serial.parseInt();
  }

  digitalWrite(h_bridge_outputs[1], bitRead(from_r_pi_dir, 3));
  digitalWrite(h_bridge_outputs[2], bitRead(from_r_pi_dir, 2));
  digitalWrite(h_bridge_outputs[4], bitRead(from_r_pi_dir, 1));
  digitalWrite(h_bridge_outputs[5], bitRead(from_r_pi_dir, 0));

  pwm = map(from_r_pi_pwm, 0, 100, 0, 255);

  analogWrite(h_bridge_outputs[0], 60); // have set tp 60 to make sure the motors work
  analogWrite(h_bridge_outputs[3], 60);
  Serial.print(pwm);
}

So that's the set up. Now everything works fine (as I've hardcoded the pwm value on the Mega) the motors go in the directions as selected in the Python terminal UNLESS I put a value in for pwm then the motor behave in an unpredictible (well to me at the moment) manner.

I dont get why when I just press enter at the pwm prompt is works fine but otherwise not? The pwm value on the mega side does nothiing as far as I'm aware.

Is there something about serial comms I'm not understanding?

EDIT: Input from the terminal

left 1: 1
left 2: 0
right 1 : 1
right 2 : 0
pwm % :

Here just hitting return for the pwm entry here. This has the effect of both motors rotating clockwise.

Values sent by the Pi (or so I think) are a byte 0b00001010 for the h bridge directions & a byte 0b00000000 for the pwm value.

Ahh hold on... Is the Arduino expecting a 16 bit integer? Is the R Pi byte 8 bit?

4
  • 2
    Please provide examples of what is sent by the Pi and what the mega receives. It might help you and us.
    – joan
    Mar 29, 2019 at 16:31
  • flushInput is deprecated. Mar 29, 2019 at 18:03
  • add some debug code to your programs ..... in the least, return the value of from_r_pi_pwm to the RPi
    – jsotola
    Mar 30, 2019 at 3:03
  • 1
    Could you please put your solution as an answer rather than leaving it in the question.
    – Darth Vader
    Apr 5, 2019 at 11:04

1 Answer 1

0

Solution to problem...

A couple of things going on here. First off was the encodeing of the bytes on the RPi side. To get a binary representation of an integer & NOT a binary representation of the string version of the integer, I used the following...

s1.write(struct.pack('<B', directions))
s1.write(struct.pack('<B', pwm))

This encodes the integers as unsigned char (ie 1 byte). Docs for struct encoding here.

On the Mega side I changed the code to wait for the serial buffer to contain 2 bytes & then read byte at a time.

void loop() {

  // Check input from R Pi & send it to the H bridges
  while (Serial.available() < 2){}

  if (Serial.available()) {
      // read the incoming bytes:
      from_r_pi_dir = Serial.read();
      from_r_pi_pwm = Serial.read();
  }

  digitalWrite(h_bridge_outputs[1], bitRead(from_r_pi_dir, 3));
  digitalWrite(h_bridge_outputs[2], bitRead(from_r_pi_dir, 2));
  digitalWrite(h_bridge_outputs[4], bitRead(from_r_pi_dir, 1));
  digitalWrite(h_bridge_outputs[5], bitRead(from_r_pi_dir, 0));
  pwm = map(from_r_pi_pwm, 0, 100, 0, 255);
  analogWrite(h_bridge_outputs[0], pwm);
  analogWrite(h_bridge_outputs[3], pwm);
}

Works perfectly!

1
  • Please accept your own answer with a click on the tick on its left side. Only this will finish the question and it will not pop up again year for year.
    – Ingo
    Jan 3, 2020 at 9:44

Your Answer

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

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