Week 8 - Embedded Programming

assignmentindividual assignment:
      read a microcontroller data sheet
      program your board to do something,
         with as many different programming languages
         and programming environments as possible
group assignment:
      compare the performance and development workflows
         for other architectures

ESP32 datasheet

I've now read my first ever datasheet. I used the documentation from the Espressif website:

https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf

I'll avoid listing all that I've read as its really best to just go directly to the datasheet when you have any questions. I've learnt that its generally a good idea to read datasheets! Here are 3 useful things I learnt about my chip:

1 - List of interfaces

There is a useful list of the peripheral interfaces. I don't know why I've never thought to look at this section of a datasheet when choosing a suitable chip. In the future I think it would be smart to write down a list of my requirements when starting a project. I can then check the datasheet to see it if offers what I require:

2 - Max power rating

I often wonder how much power I can get away with. I've blown many chips in the past and so it was interesting for the first time ever, to actually read the max power the chip can handle:

3 - Power modes

I've always been interested in the deep-sleep mode. I hope oneday to make a project that uses this mode, therefore enabling itself to run on a battery for an extended time. I have a few projects in mind that would suit such functionality. This table below shows the key info and I was surprised to see how little power this chip actually uses while in deep-sleep:

Program your board to do something

I failed to do complete this task during the original week for the assignment. I'm now updating this assignment in Week 16 and I'm pleased to say I have created my own board using the ESP32 chip. I have documented the entire process in Week 9/10:

Week 9 & 10 - Mechanical & Machine Design
individual assignment: measure something: add a sensor to a microcontroller board that you have designed and read it group assignment: probe an input device's analog levels and digital signals I've made some custom boards in previous weeks but I'd like to try something new and make a board for my favourite chip, the ESP32.
http://fabacademy.org/2021/labs/plusx/students/jonny-timms/week-9&10.html

This assignment requires me to program my board to do something and I have successfully programmed my board to do many things, as documented on my final project page:

Final Project
My idea is to make a small model town with a CNC-style machine beneath it. The machine would move a magnet around the town and could move objects such as cars, trains, skateboarders, people mowing their lawn etc. My idea was inspired by three things. This was a great example of simple project well executed.
http://fabacademy.org/2021/labs/plusx/students/jonny-timms/finalproject.html

Embed environment

I will be using the Arduino IDE and connecting to my board with an FTDI programmer that I bought from Amazon.

I have added the ESP series of boards in the IDE. To do this you must add the following text in the Arduino settings, where it asks for Additonal Boards Manager URLs: "https://dl.espressif.com/dl/package_esp32_index.json". It should look like this:

In the boards selection, you should choose ESP32 dev module. It is the first option:

Reset and boot buttons

There is a button connected to the Enable pin and a switch slider that connects the IO0 pin with ground. When you wish to upload your code, you should switch the slider to the left which will set the IO0 pin low. You also need to push the Enable button. After your code is loaded, switch the slider back to the right. Now you need to either unplug and plug it back in or use the reset button. It will now run your code correctly and give you access to the serial monitor in the Arduino IDE.

Here is a photo of my board connected to my stepper motor shield. Below that is the code that is running on my board:

const int XdirPin = 2;
const int XstepPin = 5;
const int YdirPin = 3;
const int YstepPin = 6;
const int ZdirPin = 4;
const int ZstepPin = 7;
const int enablePin = 8; //to enable the stealth chop drivers

float oldXcircle;
float oldYcircle;
float newXcircle;
float newYcircle;
float oldXmagnet;
float oldYmagnet;
float newXmagnet;
float newYmagnet;
int XnumberOfSteps;
int YnumberOfSteps;
float multiplier;

int stepPin;
int dirPin;
int XendStop = 15;
int YendStop = 15;
int XmotorSpeed = 750;
int YmotorSpeed = 750;
int ZmotorSpeed = 750;
int motorSpeed = 1000;

void setup()
{
  Serial.begin(115200);
  Serial.println("testing 1 2 3");
  delay(2000);
  pinMode(XstepPin, OUTPUT);
  pinMode(XdirPin, OUTPUT);
  pinMode(YstepPin, OUTPUT);
  pinMode(YdirPin, OUTPUT);
  pinMode(ZstepPin, OUTPUT);
  pinMode(ZdirPin, OUTPUT);
  pinMode(enablePin, OUTPUT);
  digitalWrite(enablePin, LOW);
  homeMotors();
  delay(2000);
  yAxisShift(-2000, 'A', 200);
  straight('X', 'A', 7000, 125, 125);
  straight('Y', 'A', 800, 125, 125);
}

void moveMotor(char axis, char directiony, int numberOfSteps, int motorSpeed) {

  if (axis == 'X') {
    stepPin = XstepPin;
    dirPin = XdirPin;
  } else if (axis == 'Y') {
    stepPin = YstepPin;
    dirPin = YdirPin;
  } else if (axis == 'Z') {
    stepPin = ZstepPin;
    dirPin = ZdirPin;
  }

  if (directiony == 'C') {
    digitalWrite(dirPin, LOW);
  } else {
    digitalWrite(dirPin, HIGH);
  }

  for (int x = 0; x < numberOfSteps; x++) {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(motorSpeed);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(motorSpeed);
  }
}

void powerSlide(int totalDistance, char dir, int theSpeed) {
  if (dir == 'C') {
    for (int x = 0; x < 400; x++) {
      moveMotor('X', 'C', 1, theSpeed / 2);
      moveMotor('Z', 'C', 1, theSpeed / 2);
    }
    moveMotor('X', 'C', (totalDistance - 800), theSpeed);
    for (int x = 0; x < 400; x++) {
      moveMotor('X', 'C', 1, theSpeed / 2);
      moveMotor('Z', 'A', 1, theSpeed / 2);
    }
  } else {
    for (int x = 0; x < 400; x++) {
      moveMotor('X', 'A', 1, theSpeed / 2);
      moveMotor('Z', 'C', 1, theSpeed / 2);
    }
    moveMotor('X', 'A', (totalDistance - 800), theSpeed);
    for (int x = 0; x < 400; x++) {
      moveMotor('X', 'A', 1, theSpeed / 2);
      moveMotor('Z', 'A', 1, theSpeed / 2);
    }
  }
}

void powerSlideQuick(int totalDistance, char dir, int theSpeed) {
  if (dir == 'C') {
    for (int x = 0; x < 200; x++) {
      moveMotor('X', 'C', 1, theSpeed / 3);
      moveMotor('Z', 'C', 2, theSpeed / 3);
    }
    moveMotor('X', 'C', (totalDistance - 400), theSpeed);
    for (int x = 0; x < 200; x++) {
      moveMotor('X', 'C', 1, theSpeed / 3);
      moveMotor('Z', 'A', 2, theSpeed / 3);
    }
  } else {
    for (int x = 0; x < 200; x++) {
      moveMotor('X', 'A', 1, theSpeed / 3);
      moveMotor('Z', 'A', 2, theSpeed / 3);
    }
    moveMotor('X', 'A', (totalDistance - 400), theSpeed);
    for (int x = 0; x < 200; x++) {
      moveMotor('X', 'A', 1, theSpeed / 3);
      moveMotor('Z', 'C', 2, theSpeed / 3);
    }
  }
}

void turn(int radius, int XdistanceToCentre, int YdistanceToCentre, char dir, float percentage, int startSpeed, int finishSpeed) {

  int oldXmagnet = -XdistanceToCentre;
  int oldYmagnet = -YdistanceToCentre;
  int oldXcircle = -XdistanceToCentre;
  float oldYcircle = -float(YdistanceToCentre);
  int newXcircle;
  float newYcircle;
  char Xdirection;
  char Ydirection;
  int circleMotorSpeed;
  int Xcounter = 0;
  int Ycounter = 0;
  float Zcounter = 0.0;
  float Zfigure = radius / 400.0;
  int mycounter = 0;

  for (int x = 0; x < ((float)radius * 4.0 * percentage); x++) {

    if (((oldYcircle > 0) and (oldXcircle < 0)) or ((oldXcircle == -radius) and (dir == 'C')) or ((oldYcircle == radius) and (dir == 'A'))) { //if you're in the top left quarter of circle
      if (dir == 'C') {
        newXcircle = oldXcircle + 1.0;
      } else if (dir == 'A') {
        newXcircle = oldXcircle - 1.0;
      }
      newYcircle = sqrt(sq(float(radius)) - sq(float(newXcircle)));
    } else if (((oldYcircle > 0) and (oldXcircle > 0)) or ((oldXcircle == radius) and (dir == 'A')) or ((oldYcircle == radius) and (dir == 'C'))) { //if you're in the top right quarter of circle
      if (dir == 'C') {
        newXcircle = oldXcircle + 1;
      } else if (dir == 'A') {
        newXcircle = oldXcircle - 1;
      }
      newYcircle = sqrt(sq(float(radius)) - sq(float(newXcircle)));
    } else if (((oldYcircle < 0) and (oldXcircle < 0)) or ((oldXcircle == -radius) and (dir == 'A')) or ((oldYcircle == -radius) and (dir == 'C'))) { //if you're in the bottom left quarter of circle

      if (dir == 'C') {
        newXcircle = oldXcircle - 1;
      } else if (dir == 'A') {
        newXcircle = oldXcircle + 1;
      }
      newYcircle = -sqrt(sq(float(radius)) - sq(float(newXcircle)));
    } else if (((oldYcircle < 0) and (oldXcircle > 0)) or ((oldXcircle == radius) and (dir == 'C')) or ((oldYcircle == -radius) and (dir == 'A'))) { //if you're in the bottom right quarter of circle

      if (dir == 'C') {
        newXcircle = oldXcircle - 1;
      } else if (dir == 'A') {
        newXcircle = oldXcircle + 1;
      }
      newYcircle = -sqrt(sq(float(radius)) - sq(float(newXcircle)));
    }

    int Xchange = (newXcircle - oldXmagnet);
    int Ychange = (newYcircle - oldYmagnet);

    if (Xchange > 0) {
      Xdirection = 'C';
    } else {
      Xdirection = 'A';
    }
    if (Ychange > 0) {
      Ydirection = 'C';
    } else {
      Ydirection = 'A';
    }

    int Xsteps = abs(Xchange);
    int Ysteps = abs(Ychange);

    //    if ((Xsteps <1) or (Ysteps <1)){
    //      circleMotorSpeed = regularMotorSpeed;
    //    } else if ((Xsteps ==1) and (Ysteps ==1)){
    //      circleMotorSpeed = regularMotorSpeed*0.71;
    //    } else {
    //      circleMotorSpeed = ((min(Xsteps,Ysteps)*(regularMotorSpeed*0.71))  + ((abs(Xsteps - Ysteps)*regularMotorSpeed))/(Xsteps + Ysteps));
    //    }
    //      float motorSpeedChange = float(finishMotorSpeed - startMotorSpeed)*percentageXstepsElapsed;


    float percentageXstepsElapsed = (float)Xcounter / ((float)(radius * 4.0 * percentage));
    //float percentageYstepsElapsed = float(Ycounter/(float(radius)*4.0*percentage));
    float percentageZstepsElapsed = (float)Zcounter / ((float)(1600 * percentage));

    int circleMotorSpeed = startSpeed + round((finishSpeed - startSpeed) * percentageXstepsElapsed);

    if (percentageXstepsElapsed > percentageZstepsElapsed) {
      moveMotor('Z', dir, 1, 5);
      Zcounter = Zcounter + 1.0;
    }

    moveMotor('X', Xdirection, Xsteps, circleMotorSpeed);
    moveMotor('Y', Ydirection, Ysteps, circleMotorSpeed);
    Xcounter = Xcounter + Xsteps;
    Ycounter = Ycounter + Ysteps;

    if ((Zcounter * Zfigure) < Xcounter) {
      moveMotor('Z', dir, 1, 5);
      Zcounter = Zcounter + 1;
    }

    oldXmagnet = oldXmagnet + (Xchange);
    oldYmagnet = oldYmagnet + (Ychange);
    oldXcircle = newXcircle;
    oldYcircle = newYcircle;
  }

}

void homeMotors() {

  int XendSwitch = 9;
  int YendSwitch = 10;
  pinMode(XendSwitch, INPUT_PULLUP);
  pinMode(YendSwitch, INPUT_PULLUP);

  for (int x = 0; x < 15000; x++) {
    if (digitalRead(XendSwitch) == HIGH) {
      moveMotor('X', 'C', 1, 200);
    } else {
      break;
    }
  }

  for (int x = 0; x < 15000; x++) {
    if (digitalRead(YendSwitch) == HIGH) {
      moveMotor('Y', 'C', 1, 200);
    } else {
      break;
    }
  }
}

void yAxisShift(int newYlocation, char Xdir, int theSpeed) {

  int Ycounter = 0;
  float Ypercentage = 0.0;
  int Zcounter = 0;
  float Zpercentage = 0.0;
  char Ydir;
  char Zdir1;
  char Zdir2;

  if (((Xdir == 'C') and (newYlocation > 0)) or ((Xdir == 'A') and (newYlocation < 0))) {
    Zdir1 = 'A';
    Zdir2 = 'C';
  } else {
    Zdir1 = 'C';
    Zdir2 = 'A';
  }

  if (newYlocation > 0) {
    Ydir = 'C';
  } else {
    Ydir = 'A';
  }


  for (int x = 0; x < abs(newYlocation / 2); x++) {
    moveMotor('X', Xdir, 2, theSpeed * 0.75);
    moveMotor('Y', Ydir, 1, theSpeed * 0.75);
    Ycounter = Ycounter + 1;
    Ypercentage = (float)Ycounter / ((float)abs(newYlocation / 2.0));
    Zpercentage = (float)Zcounter / 133.0;
    if (Zpercentage < Ypercentage) {
      moveMotor('Z', Zdir1, 1, theSpeed * 0.75); //because the length of the hypothenuse on triange 2 x 1 is 2.24
      Zcounter = Zcounter + 1;
    }
  }

  for (int x = 0; x < abs(newYlocation / 2); x++) {

    moveMotor('X', Xdir, 2, theSpeed * 0.75);
    moveMotor('Y', Ydir, 1, theSpeed * 0.75);
    Ycounter = Ycounter + 1;
    Ypercentage = (float)Ycounter / ((float)abs(newYlocation / 2.0));
    Zpercentage = (float)Zcounter / 133.0;
    if (Zpercentage < Ypercentage) {
      moveMotor('Z', Zdir2, 1, theSpeed * 0.75); //because the length of the hypothenuse on triange 2 x 1 is 2.24
      Zcounter = Zcounter + 1;
    }
  }
}

void straight(char axis, char dir, int distance, int startSpeed, int finishSpeed) {

  int straightMotorSpeed = startSpeed;
  int counter = 0;
  for (int x = 0; x < distance; x++) {
    counter = counter + 1;
    moveMotor(axis, dir, 1, straightMotorSpeed);
    straightMotorSpeed = round(float(startSpeed) + (float(finishSpeed - startSpeed) * (float(counter) / float(distance))));
  }
}

void loop()
{

straight('X', 'C', 10000, 200, 400);
delay(1000);
straight('X', 'A', 10000, 200, 400);
delay(1000);

//  yAxisShift(-3000, 'A', 200);
//  straight('X', 'C', 1700, 100, 80);
//  for (int x = 0; x < 400; x++) {
//    moveMotor('X', 'C', 1, 40);
//    moveMotor('Z', 'C', 1, 40);
//  }
//  straight('X', 'C', 550, 80, 80);
//  turn(748.0, 0, -748, 'C', 0.25, 80, 60);
//  straight('Y', 'A', 250, 60, 60);
//  turn(748.0, 748, 0, 'A', 0.25, 60, 40);
//  straight('X', 'C', 550, 40, 40);
//  for (int x = 0; x < 400; x++) {
//    moveMotor('X', 'C', 1, 25);
//    moveMotor('Z', 'A', 1, 25);
//  }
//  yAxisShift(500, 'C', 50);
//  straight('X', 'C', 3000, 50, 20);
//  straight('X', 'A', 2000, 60, 30);
//  yAxisShift(2000, 'A', 30);
//  yAxisShift(-2000, 'A', 35);
//  straight('X', 'A', 2000, 35, 45);
//  
// straight('X', 'C', 1000, 60, 50);
// yAxisShift(-2125, 'C', 50);
// straight('X', 'C', 2000, 60, 50);
// yAxisShift(-1200, 'C', 50);
// straight('X', 'C', 2000, 60, 50);
//
//   
//      straight('X', 'A', 2000, 60, 50);
//      yAxisShift(1200, 'A', 50);
//      straight('X', 'A', 2000, 50, 50);
//      yAxisShift(-1200, 'A', 50);
//            straight('X', 'A', 3350, 50, 50);
//
//                        straight('X', 'C', 12150, 50, 50);
//
//                          straight('X', 'A', 2000, 60, 50);
//      yAxisShift(1200, 'A', 50);
//      straight('X', 'A', 2000, 50, 50);
//      yAxisShift(-1200, 'A', 50);
//            straight('X', 'A', 3350, 50, 50);
//
//            straight('X', 'C', 12150, 50, 50);
//
//                                     straight('X', 'A', 2000, 60, 50);
//      yAxisShift(1200, 'A', 50);
//      straight('X', 'A', 2000, 50, 50);
//      yAxisShift(-1200, 'A', 50);
//            straight('X', 'A', 3350, 50, 50);
//
// straight('X', 'C', 12150, 50, 50);
//
//  delay(9999999);
//
//  for (int x = 0; x <400; x++) {
//    moveMotor('Y', 'A', 100, 100);
//    delay(1000);
  }


  //straight('X', 'C', 2000, 140, 140);
  //yAxisShift(-750, 'C', 140);
  //straight('X', 'C', 1300, 140, 140);
  //
  //for (int x = 0; x <400; x++) {
  //   moveMotor('X', 'C', 1, 70);
  //   moveMotor('Z', 'C', 1, 70);
  //  }
  //turn(782.0, 0, -782, 'C', 0.25, 450, 450);
  //turn(782.0, 782, 0, 'A', 0.25, 450, 450);
  //for (int x = 0; x <400; x++) {
  //   moveMotor('X', 'C', 1, 70);
  //   moveMotor('Z', 'C', 1, 70);
  // }
  //straight('X', 'C', 2000, 140, 140);
  //
  //delay(1000);
  //
  //
  //straight('X', 'A', 2000, 140, 140);
  //
  //for (int x = 0; x <400; x++) {
  //   moveMotor('X', 'A', 1, 70);
  //   moveMotor('Z', 'A', 1, 70);
  //}
  //turn(782.0, 0, 782, 'C', 0.25, 450, 450);
  //turn(782.0, -782, 0, 'A', 0.25, 450, 450);
  //for (int x = 0; x <400; x++) {
  //   moveMotor('X', 'A', 1, 70);
  //   moveMotor('Z', 'A', 1, 70);
  //}
  //
  //straight('X', 'A', 1300, 140, 140);
  //yAxisShift(750, 'A', 140);
  //straight('X', 'A', 2000, 140, 140);

//}


//  int counter = 0;
//  for (int x = 0; x <800; x++) {
//    moveMotor('X', 'C', 1, 65);
//    moveMotor('Y', 'A', 2, 65);
//    if ((counter % 4)==1 ){
//    moveMotor('Z', 'C', 1, 65);
//    }
//    counter = counter + 1;
//  }
//  counter = 0;
//  for (int x = 0; x <800; x++) {
//    moveMotor('X', 'C', 2, 65);
//    moveMotor('Y', 'A', 1, 65);
//    if ((counter % 4)==1){
//    moveMotor('Z', 'A', 1, 65);
//    }
//    counter = counter + 1;
//  }
//
//  moveMotor('X', 'C', 2000, 100);
//  powerSlide(4000, 'C');
//  moveMotor('X', 'C', 4000, 100);
//  delay(250);
//  moveMotor('X', 'A', 4000, 100);
//  powerSlide(4000, 'A');
//  moveMotor('X', 'A', 2000, 100);
//  for (int x = 0; x <800; x++) {
//    moveMotor('X', 'A', 1, 65);
//    moveMotor('Y', 'C', 2, 65);
//    if ((counter % 4)==1 ){
//    moveMotor('Z', 'C', 1, 65);
//    }
//    counter = counter + 1;
//  }
//  counter = 0;
//  for (int x = 0; x <800; x++) {
//    moveMotor('X', 'A', 2, 65);
//    moveMotor('Y', 'C', 1, 65);
//    if ((counter % 4)==1){
//    moveMotor('Z', 'A', 1, 65);
//    }
//    counter = counter + 1;
//  }
//  moveMotor('X', 'A', 1000, 100);
//  delay(1000);
//}}

//void curvedRail(float radius, int oldXcircle, int oldYcircle) {
//
//    int oldXmagnet = -oldXcircle;
//    int oldYmagnet = -oldYcircle;
//    float oldXcircle = -oldXcircle;
//    float oldYcircle = -oldYcircle;
//    char Xdirection;
//    char Ydirection;
//    int circleMotorSpeed;
//    int regularMotorSpeed = 100;
//
//    // SECTION 1
//
//    for (int x = 0; x <radius; x++) {
//
//    float newXcircle = oldXcircle + 1.0;
//    float newYcircle = -sqrt(sq(radius) - sq(newXcircle));
//
//    Serial.print("new xcircle value is ");
//    Serial.println(newXcircle);
//    Serial.print("new ycircle value is ");
//    Serial.println(newYcircle);
//
//
//    float Xchange = (newXcircle - oldXmagnet);
//    float Ychange = (newYcircle - oldYmagnet);
//    Serial.print("X change value is ");
//    Serial.println(Xchange);
//    Serial.print("Y change value is ");
//    Serial.println(Ychange);
//    if (Xchange>0.0){
//      Xdirection = 'C';
//    } else {
//      Xdirection = 'A';
//    }
//    if (Ychange>0.0){
//      Ydirection = 'C';
//    } else {
//      Ydirection = 'A';
//    }
//
//    Serial.print("X direction is ");
//    Serial.println(Xdirection);
//    Serial.print("Y direction is ");
//    Serial.println(Ydirection);
//
//
//    float XchangeAbs = abs(newXcircle - oldXmagnet);
//    float YchangeAbs = abs(newYcircle - oldYmagnet);
//
//    int Xsteps = round(XchangeAbs);
//    int Ysteps = round(YchangeAbs);
//
//    if ((Xsteps <1) or (Ysteps <1)){
//      circleMotorSpeed = regularMotorSpeed;
//    } else if ((Xsteps ==1) and (Ysteps ==1)){
//      circleMotorSpeed = regularMotorSpeed*0.71;
//    } else {
//      circleMotorSpeed = ((min(Xsteps,Ysteps)*(regularMotorSpeed*0.71))  + ((abs(Xsteps - Ysteps)*regularMotorSpeed))/(Xsteps + Ysteps));
//    }
//    moveMotor('X', Xdirection, Xsteps*8, circleMotorSpeed);
//    Serial.print("moving X axis by ");
//    Serial.println(Xsteps);
//    moveMotor('Y', Ydirection, Ysteps*8, circleMotorSpeed);
//    Serial.print("moving Y axis by ");
//    Serial.println(Ysteps);
//    Serial.println("");
//
//    oldXmagnet = oldXmagnet + Xsteps;
//    oldYmagnet = oldYmagnet + Ysteps;
//
//    oldXcircle = newXcircle;
//    oldYcircle = newYcircle;
//    delay(5);
//  }
//}

Here is a video to show my board working:

Group Assignment link

Electronics Design - Plus X Brighton Fab Academy Docs
General information Probes - you can change the impedence always keep it on 10X impedence PC bite No display! - press the number button The colours correlate to different channels on the oscilloscope - the knobs you should be using are also those colours - this is so you can have multiple item attached.
http://fab.academany.org/2021/labs/plusx/group-projects/electronics-design/

Files for download

Link to the group assignment:

Embedded Programming - Plus X Brighton Fab Academy Docs
Some useful notes for this Fab Academy cycle
http://fabacademy.org/2021/labs/plusx/group-projects/embedded-programming/

Back to homepage:

My Fab Academy Homepage
http://fabacademy.org/2021/labs/plusx/students/jonny-timms/