close-circle
Close

Broken but not bowed

A project log for Cardware

An educational system designed to bring AI and complex robotics into the home and school on a budget.

Morning.Star 10/20/2017 at 13:140 Comments

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