OK so I've had a good cuss at those rotten processors. Other than commenting that 'Well, I think MOST of them worked when we packed them...' just isnt good enough when money changes hands over it I'm done with them.
Maybe I'll come back to them later along with the multiprocessor networking, when I've had a break...
Meantime, fuelled by panic and a weak but nonetheless calming solution of Ethyl, I rewired the processor board after snapping off and junking the ESP partition. I had to do this, I could not get either of the two ATMega 1284P-PU chips to program. One's in a Sanguino with Sprinter installed on it, I did that myself so I know its good. Except it isnt. I wasted an hour or two on it and that followed the ESP onto the pile of failed crap I paid money for. Four Duinos and two ESPs, a handful of voltage dividers and a few chips just lately.
Oh well trusty ATMega 328P-PU's it is then. Each has its own UART and the control code on the Pi talks to the processor via the USB ports, leaving one spare for camera and one for WiFi dongle. There is the option of putting a precompiled solution on the ESP and interfacing to it via the Pi's 40-way connector using #pi2wifi .
Thats now operational and contains a working servo sequencer.
I have managed to rewrite the multicore_ini code to interface directly with the PC and got it working.
#include <Servo.h>
const int host=1; // this processor
const int servos=5;
// servo definition structure:
// articulation
// |____ servo (servo object)
// | |____ attach()
// | |____ write()
// |____ pin (physical pin number)
// |____ min (minimum range of movement 0-255)
// |____ max (maximum range of movement 0-255)
// |____ home (home position defaults to 128; 90 degrees)
// |____ position (positional information)
// |____ next (endpoint of movement)
// |____ pos (current position as float)
// |____ last (beginpoint of movement)
// |____ steps (resolution of movement)
// |____ step (pointer into movement range)
//
// packet configuration:
// byte 1: header - 2 bytes checksum
// byte 2: control - 1 byte packet type
// byte 3: parameters - 1 byte meta
// byte 3: data 1 - arbitrarily assigned
// byte 4: data 2 - arbitrarily assigned
// byte 5: data 3 - arbitrarily assigned
struct servo_position { // servo status
int next;
float pos;
int last;
int steps;
int step;
} ;
typedef struct servo_position servo_pos; // atmel c++ curiosity, substructs need a hard reference
struct servo_definition { // servo information
Servo servo;
int pin;
int min;
int max;
int home;
servo_pos position;
} ;
typedef struct servo_definition servo_def; // servo structure containing all relevant servo information
servo_def articulation[servos]; // array of servo structures describing the limb attached to it
int mins[]={ 0,0,0,0,0,0,0,0,0,0,0,0 }; // defaults for the servo ranges and positions
int maxs[]={ 255,255,255,255,255,0,0,0,0,0,0,0 };
int homes[]={ 128,128,128,128,128,0,0,0,0,0,0,0 };
unsigned char check,checksum,chk1,chk2,ctl,prm,b1,b2,b3;
void setup() {
Serial.begin(115200);
while (!Serial) { ; } // wait for the port to be available
for (int s=0; s<servos; s++) { // iterate servos
articulation[s].servo.attach(s+2); // configure pin as servo
articulation[s].pin=s+2; // echo this in the structure
articulation[s].home=homes[s]; // configure the structure from defaults
articulation[s].min=mins[s];
articulation[s].max=maxs[s];
articulation[s].position.next=homes[s];
articulation[s].position.pos=homes[s];
articulation[s].position.last=homes[s];
articulation[s].position.steps=0;
}
for (int d=0; d<1000; d++) { // garbage clear
if (Serial.available() > 0) { unsigned char dummy=Serial.read(); }
delay(1);
}
}
void loop() {
if (Serial.available() >= 7) { // if there is a packet
chk1=Serial.read(); // read the packet
chk2=Serial.read();
ctl=Serial.read();
prm=Serial.read();
b1=Serial.read();
b2=Serial.read();
b3=Serial.read();
checksum=chk1+(chk2*256);
check=ctl+prm+b1+b2+b3;
if (checksum!=check) {
Serial.write(255);
}
if ((int)ctl==1) { // servo instruction
int agl=(int)b1;
int st=(int)b2;
articulation[(int)prm].position.last=articulation[(int)prm].position.pos;
articulation[(int)prm].position.next=agl;
articulation[(int)prm].position.steps=st;
articulation[(int)prm].position.step=st;
Serial.write(64);
// Serial.write(prm);
Serial.write((int)articulation[(int)prm].position.step);
Serial.write((int)articulation[(int)prm].position.steps);
Serial.write((int)articulation[(int)prm].position.pos);
// Serial.write(st);
}
if ((int)ctl==2) { // if its a sensor data request send a sensor packet
int byte1=analogRead(A0)/4;
int byte2=analogRead(A1)/4;
int byte3=analogRead(A2)/4;
Serial.write(128);
Serial.write((int)analogRead(A0)/4);
Serial.write((int)analogRead(A1)/4);
Serial.write((int)analogRead(A2)/4);
}
if ((int)ctl==4) {
Serial.write(16);
Serial.write((int)prm);
Serial.write((int)articulation[(int)prm].position.last);
Serial.write((int)articulation[(int)prm].position.pos);
Serial.write((int)articulation[(int)prm].position.next);
Serial.write((int)articulation[(int)prm].position.steps);
Serial.write((int)articulation[(int)prm].position.step);
}
}
float ps;
for (int s=0; s<servos; s++) { // iterate servo structure
float st=articulation[s].position.last; // beginning of the movement
float nd=articulation[s].position.next; // end of the movement
float stp=articulation[s].position.steps; // how many steps to take to traverse the movement
int sn=articulation[s].position.step; // current step
if (sn>0 and stp>0) {
float df=nd-st;
float dv=df/stp;
ps=nd-(dv*sn);
Serial.write(32);
Serial.write(int(sn));
Serial.write(int(ps));
}
if (st==nd) {
sn=0;
ps=nd;
}
sn--;
if (sn<0) {
sn=0;
stp=0;
articulation[s].position.steps=0;
articulation[s].position.last=(int)nd;
ps=nd;
}
articulation[s].position.pos=(int)ps;
articulation[s].position.step=sn;
}
}
Which works as expected, but now without any of the source and destination decoding.
$ python pccore.py Closing existing port... Port not open Clearing buffers... Connected! Starting input thread. >Send bytes >Byte 1 : 4 (interrogate servo) >Byte 2 : 1 (servo 1) Servo: 1 Last : 128 Pos : 128 Next : 128 Steps: 0 Step : 0 >Send bytes >Byte 1 : 1 (program servo) >Byte 2 : 1 (servo 1) Angle : 138 (desired angle 0>138>255) Speed : 5 (steps to take to reach it) Servo: 5 5 128 Move: 5 128 Move: 4 130 Move: 3 132 Move: 2 134 Move: 1 136 >Send bytes >Byte 1 : 4 (interrogate servo) >Byte 2 : 1 (servo 1) Servo: 1 Last : 138 Pos : 138 Next : 138 Steps: 0 Step : 0 >Send bytes >Byte 1 : 2 (interrogate sensors) >Byte 2 : 0 (no parameters) Byte1: 63 Byte2: 60 Byte3: 61 >Send bytes >Byte 1 : _
That gives the Pi autonomous control of the servos, which I am now coding...
OK So now its all in there.
8 or 9 sheets of 220GSM card, a big roll of metal tape, a roll of Kapton, Superglue, PVA, 10 servos, 6 presets, 2 328s, a Pi, 2 UARTs, a handful of caps and resistors, bit of PCB, ribbon cable, bag of 3mm screws, 2x16850 cells, around 40KB of Python and C++ to control it all...
Printer, scalpel, biro, small screwdriver, cocktail stick, soldering iron...
Providing there's no magic smoke, a sleepless night should give me some motion.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.