Week 12 - Machine Week
Please refer to the group page to read about the machine we built.
Mechnical Design
Group Assignment:
- Design a machine that includes mechanism + actuation + automation + application
- Build the mechanical parts and operate it manually
- Document the group projec
Individual Assignment:
- Document your individual contribution
Machine design
Group Assignment:
- Actuate and automate your machine
- Document the group project
Individual assignment:
- Document your individual contribution
Day 1 (Monday)
Because some preparation had already been done in advance of the machine week, we already had divided tasks between us. Today I could start right away with the following tasks:
- finalize vertical drive 3D design
- draft schematic for PCB
- select electrical and mechanical components and develop circuits outside the PCB
- make or add 3D drawings of components to Fusion
Note
One thing I had prepared prior to the machine week, was to create a shared workspace in Fusion, where we could all work together on different subassemblies and create a final assembly.
Today I finished the 3D design of the vertical drive of the plate in Fusion, with three main components saved to be 3D printed.
- upper flange (holding the drive assembly in place, with seat for hall effect sensor and mounting for the motor)
- lower flange (lower bearing seat for shaft)
- drive shaft (with integrated gear, bearing seats and coupling)
We also went through the shelves of the FabLab to find suitable components for our machine and placed them in box. We selected the power supply an communication peripherals and decided to go for an external, used 12VDC 2A power supply that plugs into our enclosure and a USB-C port for easy programming (once the bootloader is burned).
Day 2 (Tuesday)
Main tasks:
- finish drawings of all purchased components in Fusion
- 3D print dial knobs
- finish KiCAD schematic
- make PCB routing and production files
- partially solder the components to the PCB
Today we finished the schematic drawing in KiCAD for the PCB that includes all the peripherals and components for our machine.
Here is a screenshot of the drawing:
Then I made the routing of the PCB traces and finished the board.
First we ran into trouble because Ólöf and I were trying to cooperate on a shared KiCAD drawing in Git. Because we weren't using the same version of KiCAD and not exactly the same library version, we had some issues to get it working.
The next issue was, that when updating the PCB from schematic only some few ratnest, but no footprints appeared. The issue was, that almost all objects were hidden for some unknown reason. See the screenshot below:
After having fixed that issue, the tracing was pretty straight forward, but I had to use some bridges and rearrange some pins for convenience.
Here is the result in KiCAD:
And here are the production files:
Here you can see what the board looked like after milling:
Here is one printed knob in front of the Fusion drawing on the screen. I printed four knobs in total (one spare).
I also soldered the microcontroller and later some other components to the PCB, so that task was finished in cooperation with Ólöf.
Because the pinout was now fixed, I could start setting up the program and worked on that in the evening.
Day 3 (Wednesday)
Today I printed the components for the vertical axis drive and now this subassembly is finished.
The fit for the bearings was very good and everything fit, except for the bearing seat in the upper flange. I made a mistake in the design and the seat was too shallow.
I could have printed a new upper flange, which takes about 4,5 h, but instead I decided to try and fix the seat in the lathe. Because it is a very small lathe, the chuck couldn't hold the hexagon on the outside. I had to make a small adaptor plate and hold the flange by mounting it with screws to the adptor plate. That was easy and took about 30 min.
After lunch it was time to assemble the drive.
Here I glued the Hall effect breakout board in place:
And here is what the other side looks like (with a HX-711 motor driver):
Gear printing
Spur gears with M 0,6 seem to be close to the lower limit of what a regular FDM printer with 0,4 mm nozzle can achieve.
Because Ólöf had already set up the bootloader on the SAMD21, I wanted to continue by testing the inputs and outputs of our PCB and get started with the program.
After uploading the first program via the USB I couldn't get any response in the serial monitor. Also the I2C didn't seem to work, because I tried displaying messages, but they didn't appear.
Failure
Unfortunately, the only logic analyzer that we have in our Lab was not available during the whole machine week, because one of our instructors took it with him to a business trip.
The later half of the day went into troubleshooting the USB connection and serial communication.
At one point we could program the board via SWD and receive an output on the serial monitor, but after that everything seemed to get worse. Our supervisor tried to assist, but in the end we had to give up - quite frustrated.
The status by the end of the day is a board that:
- isn't recognized as USB-device
- doesn't send any thing via USB
- seems to be still programmable via SWD
Question
During the troubleshooting we found two potential issues, that we could fix by adding jumper wires and a capacitor for noise reduction close to the SAMD21 voltage supply. Will it help?
Day 4 (Thursday)
This day started with continuing issues with USB and serial communication. When I had tried sending the program to a development board and even the development board stopped responding, I started suspecting the code to be the issue.
That turned out to be right. I excluded the libaries from the code and now things started working. I started going through the peripherals testing them step by step:
- the potentiometers
- the end-switch and set-switch
- the motor drivers
The LCD display didn't work so I started looking at the SERCOM functions of the SAMD21 and how to define the right pins for I2C.
If found a page that explains it, but I struggled to understand the instructions.
In the board manager core folder are files, that define the SERCOM mapping.
However, even with trying all the possibilities and adjusting different setting we weren't able to get the I2C to work.
By the end of the day we started considering and discussing possibilites of using different microcontrollers and had several options, but eventually could narrow it down to one (possibly) feasable option that would be the AVR128DB32.
Our instructor Svavar started designing a breakout board for this microcontroller while I looked at the cutting files of the enclosure and made some fixes.
Day 5 (Friday)
Today I started by cutting most of the elements of the enclosure from 4 mm MDF sheets again, after Ólöf and I had fixed some mistakes.
Then it was time for finally assembling the front panel and back panel and adding some rubber feet to the bottom.
Because I accidentally damaged the I2C pins of our board and we were still hoping to get it running with the help from Mattermost and our instructors, I made a new board, with some improvements as two 4,9k pulldown resistors to SDA and SCL (as by recommendation of our instructor).
Then we did some more testing and debugging but without any major success. We tried defining the pins Wire.begin(8,9)
and tried the Softwire.h
library as well.
Below is an image of the different boards we tried (after desoldering some components we reused).
As nothing seemed to work, our instructor had made an AVR128DB32 development board in the meantime and we tried that with the LCD screen and it worked!
That gave us the final push to redesign the whole PCB and use the AVR128DB32 instead of the SAMD21E18A.
I did the redesign and production of the new board. It took two attempts to mill it, because there was a dull bit in the machine during the first attempt.
Here is a screenshot of the new PCB:
And the design files:
After soldering and programming the new PCB it was a great relief, when we finally got the screen and some other peripherals working.
We used the DXCore for determining the pinout.
The rest of the day went into developing the different loops of the program and testing and debugging the inputs and outputs.
Day 6 (Saturday)
Today I spent most of the time programming and testing the new PCB and trying to get familiar with the settings and properties of the AVR128DB32 microcontroller in combination with the DXCore.
I wrote a homing procedure for the azimuth axis and tested and debugged it.
Additionally I made some improvements to the display and interface and tested all switches and the adjustment knobs.
Until this point I had been running the machine on USB power and hadn't connected the LED light either.
Bug
When connecting to 12V DC I realized that the machine wasn't working properly on it. The motor was quite weak and had issues turning the model and the display was very faint.
I found out, that the voltage regulator I used in the schematic was from the list of the Fab Inventory (NCV1117ST50T3G) and the one I used was marked "5V 1A voltage regulator" and had the same footprint, but was a different type and had not the same pinout!
After having fixed the board with some jumper wires and soldered new voltage regulators to it, the problem still existed.
I continued looking at the PWM control for the light and postponed the voltage regulator issue until next day.
However, the light also had an issue. It was constantly on, but the brightness changed a little bit when adjusting the PWM output.
I did some research on the Mosfet and found out (after a long while), that high-side switching with a P-Mosfet isn't a good idea, when the logic voltage and the source voltage differ. This was however, what I had drawn in the schematic.
The solution to this is to change the circuit to a low-side switching N-Mosfet.
After having drawn the changes in KiCAD I tweaked the traces and was able to rerout the 5V and GND and accomodate the N-Mosfet in a suitable loaction.
Now the light could be adjusted using the analogWrite(pin,pwm);
command.
I also added a small pin to the landscape model to point out where our Lab is located exactly.
Learnings
- Switching between power supplies on one PCB is more complicated than expected.
- When switching devices on a different voltage level using Mosfet - it is best to use a low-side switching P-Mosfet.
Day 7 (Sunday)
Today I continued working on the issue with the voltage regulator.
I measured the voltage between the +5V and GND traces on the board and I only measured 4,1 V. When my instructor came by and we took a look together, we identified the voltage drop being caused by the diode I placed. I didn't realize that diodes have such a huge loss when forwarding power.
Next I tried a Schottky diode, but still the voltage drop was too high (0,5 V).
Now I learned, that there are special IC circuits, that work like an ideal diode and should be used for applications like this, but unfortunately this wasn't available in our Lab.
A suggestion from my instructor was to put a small SMD slide switch on the board, but then we realized, that the one from the inventory can only handle 100 mA - way less then required.
I ended up using a 2-pin socket header and a jumper wire in between.
Then I tried again and now it was working great - the voltage was stable at 5V and the display not faint at all.
After having tried the motors for a while, I noticed the screen starting to become faint again. The cause this time, was propably the voltage regulator (being fed by 12V) creating a lot of heat, that couldn't be dissipated by the small copper trace and it starting reducing the output power by itself as a protection mechanism.
Because I couldn't find a suitable heat sink and I had realized by now, that I could run the motors of a powerful USB power supply I changed my mind and removed the voltage regulator from the board and made a power cable with a barrel jack and USB-conector. That seems to work fine.
Then I organized the cables and placed the PCB with the motor drives inside the box and connected the power and other cables. The red tape indicates the orientation of the connectors.
Here is a video of the homing procedure after turning on the machine and selecting a date and time and having it move to the right azimuth.
Learnings
- Diodes have a considerable forward voltage drop (and therefor power loss)
- Schottky diodes have the lowest forward voltage drop
- ICs are available that act like "ideal" diodes with no forward voltage drop
- Voltage regulators create quite some heat and require a proper heat sink
Day 8 (Monday)
Today I painted the "ocean" on the 3D printed model. As all the fjords are quite detailed and I had to use a very fine paint brush, it took about two hours to get a satisfactory result.
Note
I used water based acrylic paint and painted directly on the PLA.
The picture shows how our atificial sun is casting shadows on the newly painted landscape model.
I also worked on the program and made some improvements to the code and fixed some small bugs. Among other changes I now turn off the azimuth drive motor, when the position is reached to save energy and stop the coils from generating heat. I wonder if this will be possible for the elevation drive as well? Most likely not.
Day 9 (Tuesday)
This afternoon me and Högni met and we decided that he would need some support to finish the sun axis assembly. I made changes to the 3D design of the bracket to accomodate the support wheels in the right locations and make sure, that they can rotate freely. I improved overall strength and rigidity of the bracket and added a mount for the end switch. Then I printed all parts from black PETG.
Day 10 (Wednesday)
This morning I assembled the newly printed parts and did all the manual machining involved, as cutting bolts into exact length, countersink holes and so on. When I was happy with the arm and the bracket I added thread locker to the bolts on the arm, fastened and connected the end switch and made a trigger for it. Then I connected the motor and attached the bracket to the bottom of the enclosure.
Here are some pictures of the progress:
After lunch I wrote the last procedures for the code and tested it on the machine. Now everything works smoothly.
Here is the program for the machine in it's full length:
/* FABACADEMY 2025 - Machine Week (12)
* FabLab Ísafjörður
*
* DAYS OF DARKNESS
*
* A realistic landscape / solar model of Skutulsfjörður
*
* by Jóhannes Andrésson, Bjartur Leó Hlynsson, Ólöf Hannesdóttir, Högni Friðriksson
*/
#include <SolarCalculator.h>
#include <TimeLib.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Define Analog Inputs for poteniometer and hall effect sensor
const int ai_knob1 = 14;
const int ai_knob2 = 15;
const int ai_knob3 = 16;
const int ai_hall = 18;
// Define Analog Output for PWM of light
const int ao_pwm = 13;
// Define stepper motor constants and variables
const int steps = 48; // internal steps in motor
const float azratio = 97/10; // spur gear ratio
const float elratio = 834/10; // spur gear ratio
const float azstepdeg = 360/(steps*azratio); // deg per step
const float elstepdeg = 360/(steps*elratio); // deg per step
int azstep = 1; // azimuth step counter
int elstep = 1; // elevation step counter
float azpos; // az absolute position in deg
float elpos; // el absolute position in deg
const int do_M1P1 = 11;
const int do_M1P2 = 10;
const int do_M1P3 = 9;
const int do_M1P4 = 8;
const int do_M2P1 = 7;
const int do_M2P2 = 6;
const int do_M2P3 = 5;
const int do_M2P4 = 4;
// Define Digital Inputs (switches)
const int di_set = 24;
const int di_end = 25;
// Define Variables for solar path
double lat = 66.07243;
double lon = -23.118711;
int time_zone = 0; //UTC offset
// Define Date and Time
int yr = 2025;
int dy = 25;
int mo = 3;
int hr = 15;
int mm = 0;
// Solar position
double az; //azimuth in degrees
double el; //elevation in degrees
// Define Status Variables
bool home_az = false; // True when homing is complete
bool home_el = false; // True when homing is complete
bool run_stat = false; // True when model is running
int spd = 10; // Speed for constant operation in percentage
// Define Variables for display refresh
int lcddy;
int lcdmo;
int lcdyr;
int lcdaz;
int lcdel;
// run zenith stepper motor either forward or backward
int runel(unsigned long duration, bool dir){
static unsigned long chrono = millis();
if (millis() - chrono < duration) return;
// check if desired elevation is reached with accuracy of 1 deg
if (abs(elpos - el)< 1) return;
chrono = millis();
// make step
switch (elstep){
case 1:
digitalWrite(do_M1P1, HIGH);
digitalWrite(do_M1P2, HIGH);
digitalWrite(do_M1P3, LOW);
digitalWrite(do_M1P4, LOW);
break;
case 2:
digitalWrite(do_M1P1, LOW);
digitalWrite(do_M1P2, HIGH);
digitalWrite(do_M1P3, HIGH);
digitalWrite(do_M1P4, LOW);
break;
case 3:
digitalWrite(do_M1P1, LOW);
digitalWrite(do_M1P2, LOW);
digitalWrite(do_M1P3, HIGH);
digitalWrite(do_M1P4, HIGH);
break;
case 4:
digitalWrite(do_M1P1, HIGH);
digitalWrite(do_M1P2, LOW);
digitalWrite(do_M1P3, LOW);
digitalWrite(do_M1P4, HIGH);
break;
}
//forward or reverse operation
if(dir == true){
elpos = elpos+elstepdeg;
if(elpos > 360)elpos=elpos-360;
if(elstep < 4){
elstep++;
}else{
elstep = 1;
}
}else{ //run motor cw
elpos = elpos-elstepdeg;
if(elpos < 0)elpos=elpos+360;
if(elstep < 2){
elstep=4;
}else{
elstep--;
}
}
}
// homing function for elevation stepper motor
int homeel(bool dir){
// make step
switch (elstep){
case 1:
digitalWrite(do_M1P1, HIGH);
digitalWrite(do_M1P2, HIGH);
digitalWrite(do_M1P3, LOW);
digitalWrite(do_M1P4, LOW);
break;
case 2:
digitalWrite(do_M1P1, LOW);
digitalWrite(do_M1P2, HIGH);
digitalWrite(do_M1P3, HIGH);
digitalWrite(do_M1P4, LOW);
break;
case 3:
digitalWrite(do_M1P1, LOW);
digitalWrite(do_M1P2, LOW);
digitalWrite(do_M1P3, HIGH);
digitalWrite(do_M1P4, HIGH);
break;
case 4:
digitalWrite(do_M1P1, HIGH);
digitalWrite(do_M1P2, LOW);
digitalWrite(do_M1P3, LOW);
digitalWrite(do_M1P4, HIGH);
break;
}
//forward or reverse operation
if(dir == true){
if(elstep < 4){
elstep++;
}else{
elstep = 1;
}
}else{ //run motor cw
if(elstep < 2){
elstep=4;
}else{
elstep--;
}
}
}
// run azimuth stepper motor either forward or backward
int runaz(unsigned long duration, bool dir){
static unsigned long chrono = millis();
if (millis() - chrono < duration) return;
// check if desired azimuth is reached with accuracy of 1 deg
if (abs(azpos - az)< 1) return;
chrono = millis();
// make step
switch (azstep){
case 1:
digitalWrite(do_M2P1, HIGH);
digitalWrite(do_M2P2, HIGH);
digitalWrite(do_M2P3, LOW);
digitalWrite(do_M2P4, LOW);
break;
case 2:
digitalWrite(do_M2P1, LOW);
digitalWrite(do_M2P2, HIGH);
digitalWrite(do_M2P3, HIGH);
digitalWrite(do_M2P4, LOW);
break;
case 3:
digitalWrite(do_M2P1, LOW);
digitalWrite(do_M2P2, LOW);
digitalWrite(do_M2P3, HIGH);
digitalWrite(do_M2P4, HIGH);
break;
case 4:
digitalWrite(do_M2P1, HIGH);
digitalWrite(do_M2P2, LOW);
digitalWrite(do_M2P3, LOW);
digitalWrite(do_M2P4, HIGH);
break;
}
//forward or reverse operation
if(dir == true){
azpos = azpos+azstepdeg;
if(azpos > 360)azpos=azpos-360;
if(azstep < 4){
azstep++;
}else{
azstep = 1;
}
}else{ //run motor cw
azpos = azpos-azstepdeg;
if(azpos < 0)azpos=azpos+360;
if(azstep < 2){
azstep=4;
}else{
azstep--;
}
}
}
// homing function for azimuth stepper motor
int homeaz(bool dir){
// make step
switch (azstep){
case 1:
digitalWrite(do_M2P1, HIGH);
digitalWrite(do_M2P2, HIGH);
digitalWrite(do_M2P3, LOW);
digitalWrite(do_M2P4, LOW);
break;
case 2:
digitalWrite(do_M2P1, LOW);
digitalWrite(do_M2P2, HIGH);
digitalWrite(do_M2P3, HIGH);
digitalWrite(do_M2P4, LOW);
break;
case 3:
digitalWrite(do_M2P1, LOW);
digitalWrite(do_M2P2, LOW);
digitalWrite(do_M2P3, HIGH);
digitalWrite(do_M2P4, HIGH);
break;
case 4:
digitalWrite(do_M2P1, HIGH);
digitalWrite(do_M2P2, LOW);
digitalWrite(do_M2P3, LOW);
digitalWrite(do_M2P4, HIGH);
break;
}
//forward or reverse operation
if(dir == true){
if(azstep < 4){
azstep++;
}else{
azstep = 1;
}
}else{ //run motor cw
if(azstep < 2){
azstep=4;
}else{
azstep--;
}
}
}
void readai_stop (unsigned long duration) {
static unsigned long chrono = millis();
if (millis() - chrono < duration) return;
chrono = millis();
dy = int(float(analogRead(ai_knob1)) / 1023 * 30 + 0.5)+1;
mo = int(float(analogRead(ai_knob2)) / 1023 * 11 + 0.5)+1;
hr = int(float(analogRead(ai_knob3)) / 1023 * 23);
mm = int((float(analogRead(ai_knob3)) / 1023 * 23 - hr) * 60 +0.5);
}
void setbutton(unsigned long duration) {
static unsigned long chrono = millis();
if (millis() - chrono < duration) return;
chrono = millis();
if(digitalRead(di_set) == LOW){
run_stat = !run_stat;
}
}
void updateoled (unsigned long duration){
static unsigned long chrono = millis();
if (millis() - chrono < duration) return;
chrono = millis();
// check if values have changed - if not, return
if (lcddy == dy && lcdmo == mo && lcdyr == yr && lcdaz == int(az+0.5) && lcdel == int(el+0.5)) return;
// update line 1
lcd.clear();
lcd.setCursor(0,0);
if(dy<10)lcd.print("0");
lcd.print(dy);
lcd.print(".");
if(mo<10)lcd.print("0");
lcd.print(mo);
lcd.print(".2025 ");
if(hr<10)lcd.print("0");
lcd.print(hr);
lcd.print(":");
if(mm<10)lcd.print("0");
lcd.print(mm);
//update line 2
if(int(az+0.5)>=100)lcd.setCursor(0,1);
if(int(az+0.5)< 100)lcd.setCursor(1,1);
if(int(az+0.5)< 10)lcd.setCursor(2,1);
lcd.print(int(az+0.5));
lcd.print(char(223));
if(int(el+0.5)>=10)lcd.setCursor(7,1);
if(int(el+0.5)< 10)lcd.setCursor(8,1);
if(int(el+0.5)< 0)lcd.setCursor(7,1);
if(int(el+0.5)< -9)lcd.setCursor(6,1);
lcd.print(int(el+0.5));
lcd.print(char(223));
lcddy = dy;
lcdmo = mo;
lcdyr = yr;
lcdaz = az;
lcdel = el;
}
void solarcalc (unsigned long duration){
static unsigned long chrono = millis();
if (millis() - chrono < duration) return;
chrono = millis();
//set new time according to poteniometer input
setTime(hr,0,0,dy,mo,yr);
time_t utc = now();
// Calculate solar position
calcHorizontalCoordinates(utc, lat, lon, az, el);
}
// Adjust brightnes of the sun by elevation starting from -14°
void sunpwm (unsigned long duration){
static unsigned long chrono = millis();
if (millis() - chrono < duration) return;
chrono = millis();
int bright;
bright = int(3.6563*el+71.2);
if(bright > 254) bright = 254;
if(bright < 0) bright = 0;
analogWrite(ao_pwm,bright);
}
// Turn of motor to save energy
void stopaz (unsigned long duration){
static unsigned long chrono = millis();
if (millis() - chrono < duration) return;
chrono = millis();
digitalWrite(do_M2P1, LOW);
digitalWrite(do_M2P2, LOW);
digitalWrite(do_M2P3, LOW);
digitalWrite(do_M2P4, LOW);
}
void setup() {
analogWrite(ao_pwm,124);
Wire.begin();
lcd.begin(16,2); // Set the LCD size (16 columns and 2 rows)
lcd.backlight(); // Turn on backlight
lcd.setCursor(0,0);
lcd.print(" FABACADEMY 25");
lcd.setCursor(0,1);
lcd.print("DAYS OF DARKNESS");
// set switches with internal pullup
pinMode(di_set, INPUT_PULLUP);
pinMode(di_end, INPUT_PULLUP);
delay(2000);
analogWrite(ao_pwm,0);
}
void loop() {
// check if homing needs to be done
if(home_az == false){
//Homing azimuth axis
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Homing azimuth");
int hall_last = analogRead(ai_hall);
lcd.setCursor(0,1);
lcd.print(hall_last);
// when close to magnet reverse a bit
while(analogRead(ai_hall) < 500){
homeaz(false);
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Homing azimuth");
lcd.setCursor(0,1);
lcd.print(analogRead(ai_hall));
delay(30);
// when close to magnet
}
// approach magnet fast and stop
while(analogRead(ai_hall) > 400){
homeaz(true);
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Homing azimuth");
lcd.setCursor(0,1);
lcd.print(analogRead(ai_hall));
delay(30);
}
// find minimum value for magnet - compare with value from step before
// run until minimum has passed
do{
hall_last = analogRead(ai_hall);
homeaz(true);
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Homing azimuth");
delay(500);
}while(hall_last > analogRead(18));
// back one step
homeaz(false);
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Homing azimuth");
lcd.setCursor(5,1);
lcd.print("DONE");
home_az = true;
azpos = 180; // Home position is with sun from the south
delay(2000);
}
if(home_el == false){
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Homing zenith");
lcd.setCursor(0,1);
lcd.print(digitalRead(di_end));
while(digitalRead(di_end)==HIGH){
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Homing zenith");
lcd.setCursor(0,1);
lcd.print(digitalRead(di_end));
homeel(false);
delay(30);
}
home_el = true;
elpos = 0; //End switch is at around 0° elevation
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Homing zenith");
lcd.setCursor(5,1);
lcd.print("DONE");
delay(1000);
}
// Update solar position
solarcalc(100);
// Check if set button is pressed
setbutton(200);
// Check if model is running or stop
if(run_stat == true){
if(abs(azpos - az)> 0.8)runaz(30,true);
if(abs(elpos - el)> 0.8){
if(el<elpos && digitalRead(di_end == HIGH))runel(30,false);
if(el>elpos)runel(30,true);
}
//set brightness
sunpwm(1000);
// when position is reached, turn off
if (abs(azpos - az)< 1 && abs(elpos - el)<1)run_stat = false;
}else{
stopaz(400);
readai_stop(500);
}
// Display update
updateoled(200);
}
Here is a final picture of the machine and the group assignemnt is finished.