Hammerstein_bb.jpg (1447117Bytes)
Hi;
I am working on a web controlled rover and need a little help with fine tuning the controls, I need more precise control over the motors.
Bottom Line Up Front (BLUF)
How can I get the Arduino to process a command for a given time period, I know how to invoke a delay between commands using time.sleep(Number of seconds) but not how to run a function for a given time. My guess is that it would be in a timed loop but I don't know how to do this.
Background:
The motors are connected to an L298N H Bridge and the H Bridge is controlled by an Arduino Nano. The Nano is connected to a Raspberry Pi which sends an integer to the Nano over an i2c connection. The Nano reads the Serial data and when it receives and integer that corresponds to a set functions it runs that function, e.g. 1 = Motors Forward.
I can drive the rover forward, backwards and spin it left and right but it's the left and right that I need to control, at the minute when running the Left or Right functions the corresponding motors spin for a second which is too long small turns, in fact in that time the damm thing has nearly done a 360!!
On the Pi side in the code there is a delay of 1 second (time.sleep(1)) between reading and writing serial data which (I have read) is to avoid overload the i2c serial bus??
The solution is either PWM or Timing, however PWM is for some reason not working, the ENA and ENB connections on the L298 are connected to Digital PWM pins on the Nano but lowering the PWM using analogueWrite(Pin, PWM) just stops the motor?
The Schematic is attached and here's the Arduino code:
// Arduino Pin A5 to RPi SDA // Arduino Pin A6 to RPi SCL // Inspiration from Ocra Laing's Blog http://blog.oscarliang.net/raspberry-pi-arduino-connected-i2c#include <Wire.h>
#include <Servo.h>#define SLAVE_ADDRESS 0x04
int number = 0;
int state = 0;// Setup Ultrasonic Sensor Pins
#define trigPin 12
#define echoPin 13// Defines for reading distances
#define microsecondsToCentimeters(microseconds) (unsigned long)microseconds / 29.1 / 2.0
#define MinActionDistance 40 // Set maximum allowaable distance to obstacle// Setup motor controller pins for L298N
// Right Motor
int enA = 11;
int in1 = 8;
int in2 = 7;//Left Motor
int enB = 10;
int in3 = 6;
int in4 = 5;// Setup LED test pin
int Led = 3;// Setup the servo
Servo myservo;byte sweep_pos = 0;
byte pos_index = 90;
unsigned long left_dist, right_dist;//Set unsigned integer variables to be used
unsigned int duration;
unsigned int distance;
unsigned int FrontDistance;
unsigned int LeftDistance;
unsigned int RightDistance;void setup() {
Serial.begin(9600); // Start serial for output
Wire.begin(SLAVE_ADDRESS); // Initialise i2c as slave//Define callbacks for i2c communication
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
//Setup the servo
myservo.attach(2); //Attaches the servo to pin 2 of the Nano
myservo.write(90); //Set the servo to face front
//Below set all the pin modes as OUTPUT as they will all be outputting data
//Set modes for distance sensor pins
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
//Set modes for motor controller pins
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);//Set mode for Led test pin
pinMode(Led, OUTPUT);// Declare ready
Serial.println(“Hammerstein Ready!”);
}void loop() {
delay(100);
unsigned long dist_fwd;
//Rotate the sensor to check for obstacles
//scan(); //Call the scan function
ping();
}// Callback for received data
void receiveData(int byteCount) {
while(Wire.available()) {
number = Wire.read();
Serial.println("data received: ");
Serial.println(number);
if (number == 0) {
Stop();
}
if (number == 1) {
Forward();
}
if (number == 2) {
Left();
}
if (number == 3) {
Right();
}
if (number == 4) {
Backward();
}
if (number == 5) {
Servo_Centre();
}
if (number == 6) {
Servo_Left();
}
if (number == 7) {
Servo_Right();
}
if (number == 8) {
led_on();
}
if (number == 9) {
led_off();
}
}
}// Callback for sending data
void sendData() {
Wire.write(number);
}void scan() //This function tells the robot to scan for obstacles
{
if (sweep_pos <=0) {
pos_index = 20;
}
else if (sweep_pos >=180) {
pos_index = -20;
}
Serial.print ("pos_index = ");
Serial.println(pos_index);
sweep_pos += pos_index;
Serial.print("sweep_pos = ");
Serial.println(sweep_pos);
myservo.write (sweep_pos);
}void Servo_Centre()
{
Serial.println("");
Serial.println(“Scanning Forward”);
if (sweep_pos != 90) {
myservo.write(90);
sweep_pos = 90;
}
}void Servo_Right()
{
Serial.println("");
Serial.println(“Scanning Right”);
if (sweep_pos != 20) {
myservo.write(20);
sweep_pos = 20;
}
}void Servo_Left()
{
Serial.println("");
Serial.println(“Scanning Left”);
if (sweep_pos != 160) {
myservo.write(160);
sweep_pos = 160;
}
}void led_on()
{
Serial.println("");
Serial.println(“Led On”);
digitalWrite(Led, HIGH);
}void led_off()
{
Serial.println("");
Serial.println(“Led Off”);
digitalWrite(Led, LOW);
}//Read the HC-SR04 sensor
unsigned long ping()
{
//Trigger the sensor to send out a ping
digitalWrite (trigPin, LOW);
delayMicroseconds (5);
digitalWrite (trigPin, HIGH);
delayMicroseconds (10);
//Measure how long the ping took to return and convert to centimeters
return (microsecondsToCentimeters (pulseIn (echoPin, HIGH)));
}void Forward() //This function tells the robot to go forward
{
Serial.println("");
Serial.println(“Moving forward”);
// turn on left motor
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
// set speed out of possible range 0~255
analogWrite(enA, 200);
// turn on right motor
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
// set speed out of possible range 0~255
analogWrite(enB, 255);
//delay(100);
}void Backward() //This function tells the robot to move backward
{
Serial.println("");
Serial.println(“Moving backward”);
// turn on left motor
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
// set speed out of possible range 0~255
analogWrite(enA, 200);
// turn on right motor
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
// set speed out of possible range 0~255
analogWrite(enB, 255);
//delay(100);
}void Left() //This function tells the robot to turn left
{
Serial.println("");
Serial.println(“Moving left”);
digitalWrite(in1, LOW);
digitalWrite(in2, LOW); //Was High
// set speed out of possible range 0~255
analogWrite(enA, 0);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
// set speed out of possible range 0~255
analogWrite(enB, 255);
//delay(100);
}void Right() //This function tells the robot to turn right
{
Serial.println("");
Serial.println(“Moving right”);
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
// set speed out of possible range 0~255
analogWrite(enA, 200);
digitalWrite(in3, LOW); //Was High
digitalWrite(in4, LOW);
analogWrite(enB, 0);
//delay(100);
}void Stop() //This function tells the robot to stop moving
{
Serial.println("");
Serial.println(“Stopping”);
// now turn off motors
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
analogWrite(enA, 0);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
analogWrite(enB, 0);
}