Hi everyone. I am working on a wirelessly controlled robot, that responds and moves according to the movement of an accelerometer on a wireless controller. Basically, you tilt the controller in the direction you want the robot to move. The communication between the robot and the controller are 2 XBees. The robot uses an Arduino Leonardo, and the controller uses a 3.3V Pro Mini. The accelerometer is the 3-axis analog ADXL335. I also have an LCD connected to the Leonardo for debugging. I am also using a library called EasyTransfer for communication between the XBees, which is just serial communication.
The robot has 2 wheels, and are able to be drive in either direction, with a separate PWM speed control.
The robot uses differential drive, so when turning in direction, the wheel on that side of the robot spins slower to allow it to veer in that direction. Also, it can simply spin one motor one way and the other the other way to spin in place.
Here's how my basic program flow is:
- Pro Mini on controller reads analog values from ADXL335 accelerometer
- Pro Mini does some simple math, converts raw analog values to degrees of rotation for each axis. (0 to 360).
- Pro Mini sends a packet of data over serial to local XBee, which transmits data to remote XBee on robot
- Leonardo receives serial data from local XBee containing accelerometer data
- Leonardo uses accelerometer data to control 2 motors
- Leonardo displays X, Y, Z data on LCD
- Leonardo comes up with how to drive the motors based on X, Y, Z data.
Now, I need the motors to spin based on the amount of tilt either forward or backwards (X axis). And when turning, the turning motor has to spin slower than the regular speed motor while maintaining a relationship with amount of tilt.
Now, just for clarification, when tilting backward, the X values wrap back around to 0, and increase as tilting farther back, looping back around to 360. So when sitting level, making a 360 degree flip backwards reads X values rising from 0 to 360. Same with Y axis. Flipping leftward all the way makes values rise from 0 back around to 360.
Also, the farther you tilt forward/backward, the faster the general speed of the motors is, but the farther you tilt to the side, the slower the turning motor is in relation to the other one.
Now, my problem lies in implementing turning. I have the code down for moving forward and backward, but whenever I try to implement turning, the code doesn't do anything. As in, it doesn't 'recognize' that I'm turning or gets stuck or something. I don't know. Here's my working code on the Leonardo, with only forward/backward movement implemented:
EDIT: Because of the character limit on posts, I wasn't able to include the whole code here. Instead, I broke it into 2 parts and posted it in the following replies. I also attached a copy of my whole code. Please refer to below posts when I'm talking about stuff here.
Now, this only takes into account forward/backward X tilt, and it works great. I am using a mathematical equation to figure out PWM values instead of map() so I can modify it to figure out turning PWM values. Now, with the code above, If I modify the line:
if (driveForward == true && driveBackward == false) { // If forward
motorForward();
constXVal = constrain(mydata.xVal, forwardRangeMin, forwardRangeMax); // Constrain values that will be converted
int xPWM = (pwmFullMin + (pwmFullRange * ((forwardRangeMax - constXVal)/forwardRange) ) ); // Convert amount of tilt to PWM values
analogWrite(motorAPWM, xPWM);
analogWrite(motorBPWM, xPWM);}
if (driveForward == false && driveBackward == true){ // If backward
motorBackward();
constXVal = constrain(mydata.xVal, backwardRangeMin, backwardRangeMax); // Constrain values that will be converted
int xPWM = (pwmFullMin + (pwmFullRange * (constXVal/backwardRange) ) ); // Convert amount of tilt to PWM values
analogWrite(motorAPWM, xPWM); // Set both motors to same speed
analogWrite(motorBPWM, xPWM);}
To this:
if ((driveForward == true && driveBackward == false) && (driveRight == false && driveLeft == false)) { // If forward
motorForward();
constXVal = constrain(mydata.xVal, forwardRangeMin, forwardRangeMax); // Constrain values that will be converted
int xPWM = (pwmFullMin + (pwmFullRange * ((forwardRangeMax - constXVal)/forwardRange) ) ); // Convert amount of tilt to PWM values
analogWrite(motorAPWM, xPWM);
analogWrite(motorBPWM, xPWM);}
if ((driveForward == false && driveBackward == true) && (driveRight == false && driveLeft == false)) { // If backward
motorBackward();
constXVal = constrain(mydata.xVal, backwardRangeMin, backwardRangeMax); // Constrain values that will be converted
int xPWM = (pwmFullMin + (pwmFullRange * (constXVal/backwardRange) ) ); // Convert amount of tilt to PWM values
analogWrite(motorAPWM, xPWM); // Set both motors to same speed
analogWrite(motorBPWM, xPWM);}
To check to see if I am only tilting forward, it doesn't work. It simply doesn't recognize any movement forward, renders it obsolete, and only runs the backward tilt code that's further on.
Also, any implementation of the motorTurn() function renders the motors useless, as they don't spin. It seems that my variable xPWM is getting lost, and because of that, yPWM gets screwed up. I wish I could post a video, but my camera's dead. Also, I'll attach a few drawings I made that might help explain it more.
Basically, in short, any implemenation of recognizing Y tilt, and turning the robot fail. I simply can't implement proper turning, the way I want.
PLEASE, If you think you can help, I'll be MORE than happy to provide further information about my code/robot/dilemma!
Also, look at following posts for whole code. It's cut in the middle and divided over two posts.
LeonardoETReceiveTest2.ino (6.48 KB)