15941496_1278748628858915_4139568473045529885_n.jpgThe husk of my unprogrammed quadruped. I will hope to one day run programs that I both download as well as write,,, but for today, this is simply a picture that goes in my "learning project"JPEG Image - 140.04 kB - 01/15/2017 at 07:13 |
||
20161229_231332.pngHere is a picture of my first experiment leg.Portable Network Graphics (PNG) - 538.76 kB - 12/31/2016 at 01:25 |
||
I will have to make a "real" log to discuss my activity, but this will be a short intro because I'm not prepared to make a good log entry.
I've switched to working on my quadruped model instead of the cardboard leg,, but ALSO, am on a work trip so don't have much of my normal electronics toys with me, and also don't have a very good place to work on things.
At first when switching to my quadruped, I made a one leg movement code, driven by hard-wired joysticks, and managed to result after various different test codes and code adjustments in a leg that moves oriented around the robot's center as xyz origin.
I struggled for days (including days off from work) on making my nrf2401 transmitters work again, in the end I still have to wiggle wires to make it work, several wires are broken, but I'm sure they do work, and I think transit here just caused some ruffled feathers that took me a long time to track down. (I kept playing with the code, and the wasn't able to swap parts like I'm used to, because they are all at home).
At present I have a code which can use two buttons to select each of two legs, and drives one leg well according to xyz input, although needing constraint work,, and causes the other leg to move erratically when selected. I will just have to share everything later. ,,,, actually,, I'll just post the bad codes here, which won't work properly, only as buggy problems....
sorry, no videos at the moment,, I could make one but it's not a good video worthy part of the experiment, and I haven't been using video while on my trip so would take extra effort.
transmitter code
#include<SPI.h>
#include"RF24.h"
#define joyStick_x A0
#define joyStick_y A1
#define joyStick_z A2
#define leftFrontSelect 4
#define rightFrontSelect 2
const int lf_on = 5;
const int rf_on = 3;
int lfs_button = 0;
int rfs_button = 0;
int lfs_led = 0;
int rfs_led = 0;
RF24 radio (9,10);
byte addresses [][10] = {"0"};
struct dataStruct
{
int Xposition;
int Yposition;
int Zposition;
int lf_select;
int rf_select;
} myData;
void setup() {
// put your setup code here, to run once:
pinMode(leftFrontSelect, INPUT);
pinMode(rightFrontSelect, INPUT);
pinMode(lf_on, OUTPUT);
pinMode(rf_on, OUTPUT);
digitalWrite(lf_on, LOW);
digitalWrite(rf_on, LOW);
Serial.begin(115200);
radio.begin();
radio.setChannel(115);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_HIGH);
radio.openWritingPipe(addresses[0]);
radio.startListening();
}
void loop() {
// put your main code here, to run repeatedly:
lfs_button = digitalRead(leftFrontSelect);
rfs_button = digitalRead(rightFrontSelect);
if(lfs_button == HIGH)
{
Serial.println(lfs_button);
if (lfs_led == 0)
{
digitalWrite(lf_on, HIGH);
digitalWrite(rf_on, LOW);
lfs_led = 1;
rfs_led = 0;
Serial.println(lfs_led);
}
}
if(rfs_button == HIGH)
{
if(rfs_led == 0)
{
digitalWrite(rf_on, HIGH);
digitalWrite(lf_on, LOW);
rfs_led = 1;
lfs_led = 0;
}
}
radio.stopListening();
myData.Xposition = analogRead(joyStick_x);
myData.Yposition = analogRead(joyStick_y);
myData.Zposition = analogRead(joyStick_z);
myData.lf_select = lfs_led;
myData.rf_select = rfs_led;
Serial.println(myData.lf_select);
radio.write(&myData, sizeof(myData));
radio.startListening();
}
______________________________________
Receiver code
#include<Wire.h>
#include<Adafruit_PWMServoDriver.h>
#include<math.h>
#include<SPI.h>
#include"RF24.h"
RF24 radio (9,10);
byte addresses [][10] = {"0"};
int xJoystick;
int yJoystick;
int zJoystick;
int lf_button;
int rf_button;
struct dataStruct {
int Xposition;
int Yposition;
int Zposition;
int lf_select;
int rf_select;
} myData;
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
int SERVOMIN = 150;
int SERVOMAX = 600;
int coxa = 56;
int femur = 40;
int tibia = 60;
int camber = 10;
float x;
float y;
float z;
float rf_x = 90;
float rf_y = 40;
float rf_z = 50;
float lf_x = 90;
float lf_y = 40;
float lf_z = 50;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
radio.begin();
radio.setChannel(115);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_LOW);
radio.openReadingPipe(1,...
Read more »This log is to describe my first experiment related RF capability success.
I have managed to mostly replicate the success from my previous 3 joystick axis, 3 servo, xyz coordinate kinematics engine experiment,,, onto a wireless controller to servo driver rig.
I used the nrf24L01 module, which I suppose is the cheapest module that will easily send full interger values within the library support. (it is possible to send interger values using the cheap rf links, but not using the libraries simple commands,, it IS possible to use these easy commands with the nrf24L01).
This module is incidentally the same as the one on the Sunfounder quadruped, (I sent one of those to my dad, and studied it a little, I may buy one for myself but will wait until I have mine working,, I think that custom programming on that robot is much more difficult because of the limited equipment add-on capability,, although the sunfounder quadruped is much more well engineered set of legs than my robot will have).
My current experiment still has some issues that need to be addressed before I start playing with my little plastic robot. The leg still tries to reach where it can't for at least ONE reason, but I think more,, sometimes the kinematics engine assigns a "nan" value to the servos, and sometimes it just gets barky and I don't know exactly why, but usually towards an extreme reach. The rate of change in xyz is much to rapid, I need to tone it down. The z axis is still inverted. The leg itself is probably not exactly as my measurements suggest, resulting in some movements that don't really make the straight lines I want them too,,, and one more thing,, I think that the joysticks need to be somehow isolated from eachother's voltage inputs, because it still seems like moving x can move y when it shouldn't be. This is a hardware fix, probably using resistors, but I probably won't do anything about that sort of engineering during these phases of my experimentation.
I will post my demonstration video at the bottom, it's hard to perceive that I am trying to drive the foot in straight lines to show that the legs are bending to allow straight foot motion, but it doesn't show that well, and it doesn't show to me when I'm sitting right here either,, but I am absolutely confident that it IS doing it to some degree, so I will still post the video.
please excuse my ranting about wizards and their hands in my activity, I don't appreciate it when people affect my material and act like they aren't up to it,, but there's just nothing I can do to control my area, I don't have that kind of power. I basically can only watch it happen.
here are my two codes for this experiment.
transmit side
#include<SPI.h>
#include<RF24.h>
#define joyStick_x A0
#define joyStick_y A1
#define joyStick_z A2
RF24 radio (7,8);
byte addresses [][6] = {"1Node","2Node"};
struct dataStruct {
int Xposition;
int Yposition;
int Zposition;
} myData;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
radio.begin();
radio.setChannel(108);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_LOW);
radio.openWritingPipe(addresses[0]);
radio.openReadingPipe(1, addresses[1]);
radio.startListening();
}
void loop() {
// put your main code here, to run repeatedly:
radio.stopListening();
myData.Xposition = analogRead(joyStick_x);
myData.Yposition = analogRead(joyStick_y);
myData.Zposition = analogRead(joyStick_z);
Serial.println(myData.Xposition);
radio.write(&myData, sizeof(myData));
radio.startListening();
}
--------------------------------------------------------------------------------------------------------
receive side
#include <SPI.h>
#include "RF24.h"
#include <SoftwareServo.h>
float hipServo = 30;
float femur = 100;
float tibia = 90;
float coxaout = 40;
float coxaback = 10;
float coxadown = 30;
float L;
float A;
float B;
float G1;
float G;
float D;
float D2;
float x = 90;
float y = 0;
float z = 0;
RF24 radio (7,8);
SoftwareServo HipRotate;
SoftwareServo HipBend;
SoftwareServo KneeBend;
byte addresses[][6] = {"1Node","2Node"};...
Read more »So, first I bought some cheap "rf links" 433 mhz pairs. I tried a variety of sample codes from a variety of places, and in truth I feel like it could still work, but never managed to make a useable link that would send joystick data. I want full interger "resolution", and although there are samples of such sensor data begin sent from lots of forums, I never made it work.
THEN, I bought some nRF42L01 units, and there are a lot more examples,,, and I used the basic examples presented on the arduino wikias linked from arduino.cc. (the one that looks like notebook paper).. They are working right away, and there is also a separate advantage to them, they have an onboard data buffer which recieves the transmission, and then makes the data available to the arduino as the arduino loops to check the nrf's memory. The little rf links relied on the arduino to loop,, and I just imagine that it makes extra delay as the arduino would have to collect each transmission while the rest of the program waited. (I could be just imagining things, because data travels so quickly, ).
I haven't tried to interpret the samples into any of my experiments, but I did think it was a worthy note to make that I found a wireless link that will work. (I struggled with the wire library as well, and the wire library seems interestingly more difficult to use for this kind of sensor information exchange than the nrf24L01).
So, some of these problems are not new,, but I did not yet record or fix them.
My z axis is inverted,,, not that the joystick is inverted (although it would seem as though that would be a fix),, the actual z coordinate is opposite from what it needs to be,, so in order to assign values without joysticks I will probably have to figure out what is going on., and fix it. The equation is programming the leg position, however when the z coordinate goes more positive, the leg travels more downward. perhaps using the negative sign at the right place in the equation will fix it.
actually I'm pretty sure that my Y axis is also backward.
I don't understand exactly what is happening that is causing the leg to suddenly curl up when it nears the boundaries. Is that just what servos do? I don't think so,, , for some reason it is assigning a servo angle that can't be reached, but I don't understand how, because the xyz coordinates on my serial monitor don't take extreme leaps,, they can seem a little jumpy, but at other times it is clearly just the servo reaching for a different location than the coordinates on the screen. I will play with a serial monitor for angles as well,, but I don't know if that's my answer either. On the one had I want to have stable boundaries, but on the other hand I don't want to sacrifice mobility for tight little xyz windows. thinking aloud, perhaps there is a circle equation that can define my xyz boundaries, as a square is actually not logical for an arm that swings on a central axis. (this would also be an equation where in truth there are offsets to be considered, however these offsets will probably be problematic for me).
other note: really, I don't want my joystick to be right on top of the leg,, I want it to reach a ways. I will of course not want to make very long wires for each joystick axis + power and ground,, and then later if I want buttons, etc.,, but I haven't succeeded in making a working transmit of decodable data using my new transmit/receiver pairs. (those super cheap ones, mine are MX_RM_5V, 5 pairs for 9 bucks on amazon). ,, so perhaps I will use my cannibalized usb wire to give me a few feet of reach to another UNO, which will communicate via serial to the robot controller,, by sending joystick data. I also don't want to use XBEE.,, actually I DO need to study that (I can't afford it now),, because I also want to stream sensor data from my robot to a raspberry pi,, or possibly my desktop,, where I will try to learn sensor mapping and data collection. There are a lot of examples of people using "processing" to make sensor displays, although from my standpoint this is a lofty goal.
perhaps I can tune those transmitters to another frequency in the programming, which would allow my controller to be transmitting to the robot, and the robot to be transmitting to the pi, and using the same cheap transmitter without interfering.
This experiment is an xyz coordinate for foot position, which is moved by affecting the joysticks to move the coordinates at intervals related to the deflection of the joysticks. There are two joysticks, but one axis is ignored for this experiment. The leg initiates at "90 degrees extended and comfortably bent", and then you can move it around a 3d plane by pushing the joysticks, and when you do not push the joysticks the leg stays put. (there are several experiments that connect the foot position directly to joystick position, but in my experiment series this is done using potentiometers,, this experiment is specifically to allow the user to push up, and the foot moves up, etc.).
This experiment will hopefully move my programming toward a selectable foot which is placed by joysticks, with the body of the quadruped also moving to account for the new balance and shared stretch (not just one leg will move, all 4 legs will move to help the robot reach the new foot position and maintain balance and/yet share the extension,,,) . This leg experiment is only a very small piece of the required programming, but is a fundamental concept for my desired operator capability.
I had one error where I put a plus sign instead of an equal sign,, otherwise the bulk of the program was identical to the potentiometer experiment (which also saw me doing similar things). ,, otherwise the method of joystick input is fairly easy. Again in my code are some variables that are not used, but I will have to rework the program again, to fix the kinematics. This is because although it would be wonderful if my robot were just straight lines from and at each angle, this is not the case. The servos cause each joint to have both an angle,, and an offset (which is because the servo takes up space in my case, but in reality all robots will need to have little offsets figured in everywhere). I tried to program a kinematics equation the would put my foot exactly where assigned, rather than just moving according to my inputs, but I had quite a bit of trouble with stability until I erased all of these extra lines, and just went ahead with the bare minimum kinematics which does put the angles basically correct, but places the foot about 20mm away from the assigned xyz.
Below the code is a video demonstrating the build. Only just now I thought that I do not describe the wiring,, but I will have to leave it out for now, I don't make those kind of diagrams and would have to learn it.... The pins are, however, assigned in the code.
#include <Servo.h>
#include <math.h>
Servo hipRotate;
Servo hipBend;
Servo kneeBend;
float hipServo = 30;
float femur = 100;
float tibia = 90;
float coxaout = 40;
float coxaback = 10;
float coxadown = 30;
float L;
float A;
float B;
float G1;
float G;
float D;
float D2;
float x = 90;
float y = 0;
float z = 0;
void setup() {
// put your setup code here, to run once:
hipRotate.attach(9);
hipBend.attach(10);
kneeBend.attach(11);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
int joyx = analogRead(A0);
int joyy = analogRead(A1);
int joyz = analogRead(A2);
int xShift = map(joyx, 0, 1023, -10, 10);
int yShift = map(joyy, 0, 1023, -10, 10);
int zShift = map(joyz, 0, 1023, -10, 10);
if (xShift == -1 || xShift == 1) xShift = 0;
if (yShift == -1 || yShift == 1) yShift = 0;
if (zShift == -1 || zShift == 1) zShift = 0;
x = x + xShift; y = y + yShift; z = z + zShift;
if (x >= 180) x = 180; if (x <= 0) x = 0;
if (y >= 180) y = 180; if (y <= -180) y = -180;
if (z >= 160) z = 160; if (z<= -200) z = -200;
G1 = atan(x/y) ;
float G2 = degrees (G1);
if (G2 <= 0) {G2 = 180 + G2;}
D = sqrt ((x*x) + (y*y));
D2 = sqrt (((D+coxaback)*(D+coxaback))+(coxaout*coxaout));
L = sqrt((D2*D2)+((z+coxadown)*(z+coxadown)));
A = acos(((femur*femur)+(tibia*tibia)-(L*L))/(2*femur*tibia));
B = (acos(((femur*femur)+(L*L)-(tibia*tibia))/(2*femur*L))+acos(((L*L)+((z+coxadown)*(z+coxadown))-(D2*D2))/(2*L*(z+coxadown))));
Serial.print (x);
Serial.print(" ");
Serial.print(y);
Serial.print(" ");
Serial.println(z);...
Read more »So I want to make some notes because if I don't there will be less notes on the 3d 3 servo experiment, and I had a lot of trouble with the code so I want to get as much trouble into my notes. I struggled with the angle of the hiprotate servo in particular, because even after all of my stupid errors were fixed, my hiprotate servo would stay in only 90 of the 180 possible degrees, and then it would skip to max 0 (which I wanted to be 180 but it's backwards still), and try to occupy a negative degrees counting back down from 90 for each degree is should be closer to 180. This is because of my axis orientation choice, which is as follows:
The leg rotates on the x,y axis, which is parallel to the ground/body plane. the x axis extends straight out from the body, and the y axis is positive in front of the leg, and negative behind the leg, which means that y0 is stretched straight out from the body. The equation for the leg (which is very standard and based on the simplest possible function to find the angle (least work),) will in my case be calculating a possible y coordinate from -180mm to +180 mm (my leg is about 180mm fully stretched). This number generates 90 degrees, therefore, at the y 0, and then at y -1 it generates - 89 degrees. So I had to enter "" if angle is < 0 , map ( - 90 , 0 , 90 , 180 ) . .. My leg, however, drives backwards from the xy axis as entered, so if the potentiometer value is mapped to a postive y location, the leg will occupy the negative location instead.
I will not share my code just yet, because of the amount of problems that still have skeleton in my code, and because it's basically broken still. I tried to measure and equate the various measurements of the leg that would offset the position if not accounted for,, for example the servo for the knee causes the foot to be about a cm out from the line made by the femur, and I did manage to have some numbers work for me, the distance the leg is set out by the hiprotate servo and hipbend servo makes an extra triangle (so I added the offset of the knee to this number, but this equation is ignored by the current angles used as I was unable to produce a number from that equation, I read "nan" on serial monitor.), it also holds the leg back because the servos are squared to each-other (this part seems to be working), not aligned according to the servo outputs. The z offset is working ok.
I will add some videos at the bottom. I understand these videos are not of usable quality, but they do demonstrate my current situation, for example my leg popping off because I don't want to screw it on,, as well as what the motion actually looks like.
(I am having a "personal" moment with my leg popping off, where I know that almost everyone will say "just put the screw in, quit being ""a way"" about it", and then I'm going to continue to leave the screw out (the other two are in, but for this kind of thing I have to point the finger at wizards and their influence, it's not really my fault if I think I shouldn't have to do it,, I also won't write my equations out. I feel that having to write things down is both beneficial, and also sacrificial, and as we move further into the future, I should expect to not be able to write things down and be forced to simply look at those presentations that are already in existence,, so if I am looking at a webpage, the only reason I need to then write it down is because I was taught to do that,, in truth the human being doesn't need to do this at all, if they had practiced learning without having to scribble then they could do it,, and again, there are powerful spells associated with writing things down, because it has been used so many times as proof of understanding regardless of actual understanding. I would argue that when people suddenly understand from writing things down, they are actually experiencing a wizards reward, where a block is lifted BEFORE the kind of understanding that writing would have granted is achieved,, --in order to...
Read more »Today I made to working order (very simple, no stability engineering) a joystick controlled x,y directed foot for a 2d 2 servo leg. (as pictured previously).
I will post an 8 minute video below the code. I do have some trouble. If I move the foot outside of the constraints, it sends both servos to 0 degrees, however if I move the x,y back within the constraints the foot returns to where it got lost, and drives as directed. (mostly). There are still some issues with position,, if the hip servo can't move past 180, the tibia continues to swing upward, placing the foot further away than the directed x,y coordinate. I don't understand constrain,, I was under the impression if I constrained x and y, then they should remain at their limitations, instead the program must assign some random value. I will probably need to use "if" statements to set x and y to their constraint values if the arduino tries to set them outside of the constraints. (unfortunate because then the constraint function is pointless?? I could simple use the "if" statements alone in that case.
The basics of the program are good. I will start thinking about 3 dimensional equations now. I have made a simple wheelie bot that uses a differential drive equation, so I am slowly picking up on the basic kinematics of a few different degrees of motion. I can basically visualize all of my successful experiments thus far.
My code is pretty basic, and I think it is easy to understand. There are a lot of "Serial.print" functions which I used for troubleshooting, but I am leaving them in there for now. I like the idea of being able to see each step of the processing. the more servos there are, the nicer it will be to see the chart of each step of the computation.
I have been seeking others codes, and aim to collect any codes written by others that accomplish similar tasks that my codes, and prospective codes will do. As I am new to programming, I will not use any more libraries that absolutely necessary, and so am especially hoping to see more codes that do not reference libraries, or overly shorten each math statement with too many variables that ONLY shorten those important lines. (for example, making a variable for squared variables,, I understand that many are simply more accustomed to seeing these shorthands throughout a code,, however for my visualization, I prefer to skip them, and hope to see more codes where only the absolutely required language is used.
In this experiment, I had trouble with organization and syntax, and although I didn't change any of the "meat and potatoes", I did have to sit more than once after arriving at the proper functions to result in a working code.
//servo leg experiment. 2 servos moving on a 2 dimensional x,y coordinate plane. hip servo at 0,0
//hip servo oriented such that 0 degrees is straight downward, and 180 is straight upward
//knee servo oriented so that 0 is directly toward femur, and that 180 is directly away from tibia (so 180 fully extends the leg)
//my model is backward, with the leg extending to my left, so I input negative values and it seems to want to work
//there are still problems with this code, the solutions it may pick may not be within the range of motion of the servos.
//all measurements are in milimeters.
//open serial monitor to see angle B then angle A, B is hip angle so printed first
#include <Servo.h>
#include <math.h>
Servo hip;
Servo knee;
int femur = 100;
int tibia = 90;
int joyx ;
int joyy ;
int x = 90;
int y = 90;
float L;
float A;
float B;
void setup() {
// put your setup code here, to run once:
hip.attach(9);
knee.attach(10);
Serial.begin(9600);
L = sqrt((x*x)+(y*y));
A = acos(((femur*femur)+(tibia*tibia)-(L*L))/(2*femur*tibia));//outputs number in radians as A
B = acos(((femur*femur)+(L*L)-(tibia*tibia))/(2*femur*L))+acos(((L*L)+(y*y)-(x*x))/(2*L*y));//outputs number in radians as B
Serial.print(degrees(B));//converts radians to degrees
Serial.print(" ");
Serial.println(degrees(A));//converts radians to degrees
hip.write(degrees(B));//converts...
Read more »So I've managed to rig up an experiment with my little leg, where I use two potentiometers mapped to x and y coordinate ranges to direct the foot location. It never worked perfectly, but did display some "workingness".
I noticed that when changing one potentiometer, the other potentiometers input would also change (although less,, I don't say slightly because it was certainly noticable). I think this is because when one potentiometers resistance would change, the current flowing through the other potentiometer would be affected. This is probably because the entire circuit is two potentiometers, and two servos (drawing power from arduino directly,,, lights flickering), all connected to power in parallel. So although the pot outputs run to two seperate pins, an important amount of voltage flows to ground, which is what will change the most as the other potentiometers value is changed. This would certainly result in a change in value at the analogRead, and therefore (in my case) a change in y coordinate (mostly y,, x was more stable,, probably the range of motion was mostly in a different place on the potentiometer, meaning the resistance to ground was significantly different between the two pots for the range of motion I was within).
I did manage to get some good motion out of the leg, though. I very clearly saw it move MOSTLY along the changes in x or why I input.
my rig is very unstable. The servos are jumpy, one of them wags. I switched it with one that had previously shown to be more stable, but now it wags,,,. I bought both wagging servos at radioshack,, but now am thinking it might be because the cardboard arm is a generally very unstable place to be mounted, resulting in lots of movement that might cause bouncing connections, or other distortion.
I have more videos of the experiment and problems (although also the successes), but I will keep it to one at the very bottom of this log. I will put the link after the code for the experiment, which is next.
Unfortunately, I did lots of little things to the code over time, so exactly the code for experimenting might be a touch different. I did use a much longer delay in order to allow for me to watch the serial.print a little more easily. However, the code as it is was running only moments ago and producing the desired (well,,, from the code anyway) results. I would probably benefit from some more well produced physical equipment. nice machining,, all that jazz. For now, though, I am able to worry about certain fundamentals.
//hip servo oriented such that 0 degrees is straight downward, and 180 is straight upward
//knee servo oriented so that 0 is directly toward femur, and that 180 is directly away from tibia (so 180 fully extends the leg)
//my model is backward, with the leg extending to my left, so I input negative values and it seems to want to work
//there are still problems with this code, the solutions it may pick may not be within the range of motion of the servos.
//all measurements are in milimeters.
//open serial monitor to see angle B then angle A, B is hip angle so printed first
#include <Servo.h>
#include <math.h>
Servo hip;
Servo knee;
int femur = 100;
int tibia = 90;
void setup() {
// put your setup code here, to run once:
hip.attach(9);
knee.attach(10);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
int joyx = analogRead(A0);
int joyy = analogRead(A1);
int x = map(joyx, 0, 1023, -250, 0);
int y = map(joyy, 0, 1023, -150, 150);
Serial.print (x);
Serial.print (" ");
Serial.println (y);
//assuming servo hip is oriented, 0 straight down, 180 straight up, y is inverted, so -y is above the x axis
float L = sqrt((x*x)+(y*y));
float A = acos(((femur*femur)+(tibia*tibia)-(L*L))/(2*femur*tibia));//outputs number in radians as A
float B = acos(((femur*femur)+(L*L)-(tibia*tibia))/(2*femur*L))+acos(((L*L)+(y*y)-(x*x))/(2*L*y));//outputs number in radians as B
Serial.print(degrees(B));//converts radians to degrees
Serial.print(" ");
Serial.print(degrees(A));//converts...
Read more »So I have successfully completed the first part of my first quadruped leg programming experiment. I have managed to send the foot of a 2 dimensional 2 servo leg to an x,y coordinate.
to choose a new coordinate, the program must be modified (the x and y intergers) and reloaded, but it DOES use an Inverse Kinematics equation to assign the angles to the servos. Much of my difficulty came from trying to learn how the equations should look, some of it came from errors in program organization and io assignment.
Here is the code.
----------------------------------------
//servo leg experiment. 2 servos moving on a 2 dimensional x,y coordinate plane. hip servo at 0,0
//hip servo oriented such that 0 degrees is straight downward, and 180 is straight upward
//knee servo oriented so that 0 is directly toward femur, and that 180 is directly away from tibia (so 180 fully extends the leg)
//my model is backward, with the leg extending to my left, so I input negative values and it seems to want to work
//there are still problems with this code, the solutions it may pick may not be within the range of motion of the servos.
//all measurements are in milimeters.
//open serial monitor to see angle B then angle A, B is hip angle so printed first
#include <Servo.h>
#include <math.h>
Servo hip;
Servo knee;
int femur = 100;
int tibia = 90;
void setup() {
// put your setup code here, to run once:
hip.attach(9);
knee.attach(10);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
int x = -150; //change this value to assign a new desired x coordinate, and re-upload program
int y = 60; //change this value to assign a new desired y coordinate, and re-upload program.
//assuming servo hip is oriented, 0 straight down, 180 straight up, y is inverted, so -y is above the x axis
float L = sqrt((x*x)+(y*y));
float A = acos(((femur*femur)+(tibia*tibia)-(L*L))/(2*femur*tibia));//outputs number in radians as A
float B = acos(((femur*femur)+(L*L)-(tibia*tibia))/(2*femur*L))+acos(((L*L)+(y*y)-(x*x))/(2*L*y));//outputs number in radians as B
Serial.print(degrees(B));//converts radians to degrees
Serial.print(" ");
Serial.println(degrees(A));//converts radians to degrees
hip.write(degrees(B));//converts radians to degrees
knee.write(degrees(A));//converts radians to degrees
delay(50);
}