Project Journal for Craig Eagleburger

=============== Week 15: =================

Entry 7: -----------------------------------------------------------------

Date:April 24th

Start Time: 3:30 pm

Duration:2.5 hours

Going to calibrate the feed of second to last slot, since it commonly sends both of the last cards. First I adjusted the stm code to change the parameters before firing into slot 1, feed the slot, and return them to what they were before. Ideally this would be done on the pi since the stm code is designed to be unaware of the control flow, but sending commands with four four-byte parameters would be very annoying with the current stm interface on the pi, so I am doing it on the stm in the interest of time. I first made the new parameters the same as the old ones and flashed it to the stm to ensure the code did not break anything. I flashed this right away, since I did not want to spend a lot of time calibrating, then realize at the end that the stm code doesn’t work and frantically debug. We loaded two cards and sent a command to load slot 1, then slot 0, and saw that it still worked. I then started calibrating with Johnny and Brendan. Our first thought was to shoot for less time and decrease the delay between when the motors move forward and when the rear motor moves back. We tried this, and saw that the cards were basically coming out perfectly on top of each other. To try to split them, we ran the motors at lower power. This worked, since the cards split slightly, but the cards didn’t fully come out since the motors were weaker. We increased the amount of time the motors would move forward. Still, both cards would sometimes be fed. We then decreased the delay further, and increased the amount of time they would move forward even more. This resulted in a perfect feed every time, and honestly looks better than any other feed we have used. We decided not to calibrate the feed for the rest of the deck, since it is already feeding one card 100% of the time and changing the feeder parameters may affect the position of the card when the camera takes a photo.

example3

We then had our demo at 4:30. Everything worked perfectly for the first test, which output the deck in opened pack order. The second test was a poker game mode that dealt out a royal flush. This also worked perfectly. We were out of time, but we had joked before that we should demonstrate the phone number gamemode with Dr. Walter’s phone number to surprise them. This unfortunately did not work, as the computer vision misidentified a couple of cards. Overall, the demo went great and was very rewarding.

We planned what changes we would make before Spark challenge, planned to meet saturday for lunch at Taste of India then write / film our video.

Entry 6: -----------------------------------------------------------------

Date:April 24th

Start Time: 11:45 am

Duration:2.5 hours

We decided to finally add the improvement that we have been considering, where the wheel would move up to ensure the last card falls into its slot before starting to dispense cards, since we were getting some jams when the wheel tried to move downwards after dispensing the last card. I added a line in the main pi code after feeding all slots that would send the command code for align the feeder to slot, then sent 35 as the parameter, which would definitely move the wheel up enough to let the card fall in. This line won’t be able to be tested completely until the algorithm code stops erroring.

We are still having errors on our algorithms code. Krish wrote code to make the vision output a deck of 52 different cards no matter what. We ended up just randomly assigning missing cards to duplicate values that had lower confidence. This code appears to result in a list of cards 1-52, but we are still encountering an error. We spent a long time as a group debugging. Krish had to leave to go to class and take an attendance quiz. Looking at the output of Krish’s code, I realized that the cards indexes are going from 0-52. I looked at the computer vision code that fixes duplicates, and realized it was using a new data structure that held accuracies. Looking at the computer vision code that stores this, I saw that it was indexing into this data structure with 0-51. It needed to be offset by one to work with Krish’s algorithm code, which indexed the slots starting at 1. After fixing this, the algorithm code now completely works!

We are now getting an error when dispensing cards. The pi is receiving a UART signal of 60 from the stm instead of the slot number as an ACK. This is definitely related to the code I used to send the alignment command. I was confused as to how the stm would send a 60, but just adjusted the pi code to flush the input buffer before dispensing. This fixed the error. I realized after the 60 was the ASCII code for ‘<’, which is the first character in the “” message I send when the STM is expecting parameters for a command. This was useful for the send_commands.py function. Ideally I would add a command to the stm that enables/disables these parameter messages, since they complicate the Pi code unnecessarily, but at this point we are focused on time.

After fixing this, we were able to test many modes, and they all were working. We officially are in a better spot than we were 24 hours ago when we showed the course staff the unopened pack mode almost working perfectly. Our project is demoable. The one change I want to make is calibrating the feeder for the second to last slot to prevent double feeds, but this will not take very long, so I decided to go to my shift for HKN lounge because there was no need to skip.

Entry 5: -----------------------------------------------------------------

Date:April 24th

Start Time: 12 am

Duration:8.5 hours

Submitted a project for another class before midnight, then met with group to attempt to get everything working before demonstration. Main issues when I arrived was a replacement servo was becoming extremely hot, the gate was skipping, the algorithm code was erroring out for many modes, and the computer vision was not very accurate.

To fix the gate, we first tried gluing the servo down to be more parallel with the slot. This did not work, and the servo was heating up so much that the glue was melting. There was probably a short in the servo with very low resistance that was drawing lots of current. We returned to using the original servo. At some point Johnny went to print a new iteration of this gate that bulged into the wheel slightly, and this solved all the gate problems. I told Johnny that the weight holder was blocking the last card from coming back in, which would cause jams and problems detecting the last card. He printed a larger weight holder that would stay on top of the card, so it wouldn’t get stuck.

Next, we wanted to fix computer vision, since it seemed to be performing worse than it was before. Krish and I decided to take pictures of the most commonly confused cards, and the algorithm would check these additional reference pictures after detecting one to try to get a higher confidence value and avoid confusion between 3/5 , 6/8 for example. After taking these pictures, we realized there was a spot on all of them. We cleaned the lens multiple times, but the spot remained. We determined that something had somehow gotten into the camera. We removed the camera, and unscrewed the lens. The obstruction fell out, but the feeder’s hot glue also got detached from the PSU in the process. We put the camera back, then tested computer vision again. The accuracy was very low because the camera’s position and focus had changed slightly during the cleaning process. We then started taking new pictures. We used the command line camera script I had written the other day and used send_commands to feed different slots. While we were doing this, the feeder stopped feeding properly. The front motor was no longer working. We hooked it up directly to another 12V power supply, and it worked fine. All connections were good, and we tested the pwm input to the pin, and it looked good. We determined the motor driver was no longer working.

Johnny and Krish started trying to desolder the motor driver. I started to test motor drivers. I set up a bunch of wires from power supplies to test them, giving 12V and 5V power, and 3V input signals. I made one input pin 3.3V and the other gnd, and gave 3V input to the enable pin. The driver I tested seemed to work. It generated a 12V output on the output pins, which became -12V when I switched which input pin was high. It also worked when I tested the other side. I set this driver aside to be soldered on if Johnny and Krish were successful. I then started trying to flash the backup PCB that Brendan soldered for this kind of situation. Plugging it into power caused no fire, which was good. However, after hooking up the ST-LINK, it was not flashing. I messed with a bunch of debugger settings in CubeIDE, but I kept getting an error saying no device was found on target. Online, it says the pins that should be correct for the stm to be able to flash were boot0, reset, SWCLK, SWDIO, and power. I referred to the schematic while Brendan probed the PCB to see if all of these had the proper input. They appeared to, so Brendan checked if all of the solder connections of these pins looked good. He came back and said he resoldered the reset pin. Plugging it in again, it was able to flash. We then started plugging in one subsystem at a time to see if everything worked. First, we tested the DC motors. We loaded up the main code on the pi, sent a config, and pressed the start button. We expected the motors to start feeding. They did not. I realized this was because the STM was still in homing mode, so we connected the homing sensor. After redoing the startup and tripping the homing sensor, the motors started moving. We next connected the wheel, then the servo. Everything worked which was a big relief. This PCB does look a lot nicer because all of the header pins are cut cleanly and male rather than janky, broken female header pins. However, this change means we needed a bunch of new wires. The group behind us was also there grinding and they offered us some female to female wires, which we desperately needed. However, it was not enough and we started cannibalising the breadboard for more. Eventually everything was wired properly. At some point during this Johnny and Krish reported that the old PCB was no longer usable, so it is very nice that this PCB worked. In case this happens again, Brendan started soldering a third PCB.

Now that everything is working again, we need to realign the feeder. We ran a full feed, and the feeder appeared to be in a good spot, so we glued it down. Now we need to retake the computer vision pictures, which was our original goal. After doing so, the computer vision was performing slightly better. We were able to get all spades correct in an unopened pack, but the other suits were complete garbage. Since the camera had moved slightly, Krish checked how good the crop that the CV code was making was. It was very bad, and the numbers were getting half cut off. It is a mystery as to how the spades came out correct. We spent a long time trying to get the crop to be better, as Krish was having problems getting the crop to output something different. We eventually realized he was looking at the wrong output file, and he was changing the crop the whole time. After fixing this, the computer vision was much, much better.

The algorithm code is having errors. We determined that this is because all of the algorithm code expects a valid order coming from computer vision, but our inputs have many duplicates or even None. We had a long discussion about different fixes to this, including storing the top X accuracy values for different cards, and adjusting when a duplicate card is detected. This would almost guarantee that each card in the list would have the highest confidence value for the card that it is assigned to. However, there are many edge cases to consider here, and we would have to edit our data structures, and overall it adds too much complexity. It would also cause cascading effects, since if we want to add a duplicate, then see that we have a higher confidence value, and try to move the original to it’s second highest confidence value, but that card is already in the list, we would need to recurse on the algorithm, and would need to store even more accuracies. Krish had an idea involving maintaining some kind of set, but my brain was too fried to comprehend the words coming out of his mouth. We decided to take a break and come back in a couple hours. We knew the last thing to fix was getting CV to output a valid order, and everything else would fall into place.

Entry 4: -----------------------------------------------------------------

Date:April 23rd

Start Time: 9:30 am

Duration:4.5 hours

We set up the newly printed construction that Johnny made. Testing new computer vision that Krish made that should be slightly faster, since it only compares to cards of the proper color. We realized most mistakes made by computer vision didn’t make sense - confusing 2s and Qs, 3s and Js. We looked through the code and found that the labeling of the cards in code did not align with the order of the reference images in the reference images folder. Some suits that were ordered K-A were being labeled A-K, hence why queens were being labeled as 2s. Swapping this resulted in much more accurate computer vision. We discussed computer vision approaches - sync vs async. Async would allow us to dispense 50 cards as fast as possible, and run computer vision in the background. This would result in waiting for CV to finish processing after all cards have been fed. Not sure if pi has memory requirement for this, may need to store images to SD, which would slow down the overall processing time. For now, we use sync - wait until computer vision is done processing to feed the next card, as we know this will work for the demo. New collector tray works well until end, when it gets too full and cards get stuck on it. Needs to be deeper. It also needs the gate to open more to allow cards to fall out. Flashed new gate angle and lower speed. Skipped at lower max speed - want some more speed to help prevent getting stuck. Flash with 170 open gate angle and 2.0rps maxed speed. This worked better. Tested alignment of new construction and glued once it was in place. Sometimes shooting two cards at the end. New weight was more than the old tape and solder combo. Experimented with new weight values, used 20g instead of 50g. Discussed design of PCB holder. USB C broke, powered using pins. Discussed using Pi 4 instead of 0 for spark for faster CV. Discussed how to detect when card was not properly dispensed.

Entry 3: -----------------------------------------------------------------

Date:April 22nd

Start Time: 10:30 am

Duration:3 hours

Since our computer vision output is based on images taken at random times, we will change our control flow code to take images when we know the card is in the proper slot. I changed the vision code to be a class that stores the current order of cards and has methods to take a picture, process a picture into a certain slot, and reset so it is prepared for back-to-back shuffles. The main logic will take a picture, then feed the card, then process the image. In the future, this code should check if the processed card was also in the previous slot, and let the main code know so it re-feed that empty slot. Note the “vis.” functions in this main code:

example3

We tested powering the Pi from the USB port, and this worked.

I noticed Krish’s algorithm code uses slot indexes from 1-52, while the main pi code and my stm code uses slot indexes 0-51. Since changing this on either side will require changing many things, I changed the computer vision to offset it’s output by one, since this is basically the interface between the stm/main code and the algorithm code. I also timed how long capturing and processing image takes and output it to the console while feeding. Capturing is basically instant, processing image is ~1.2 seconds.

To try to improve the vision accuracy, I took 52 updated pictures. To do so, I wrote code to save each image and it’s associated guess to an image file. The images look good and the card is positioned well, but the guesses are still very off.

Want to set up the vision code so we can check the guess and see image while sending commands, so we can check on its accuracy.

Entry 2: -----------------------------------------------------------------

Date:April 21st

Start Time: 5:00 pm

Duration:4 hours

Trying to run integration code that uses Krish’s computer vision code. It was unable to run because of an error when starting the camera. The error is related to opening up a window. Looking up this error, I have to run export DISPLAY=:0 before running the main code. This worked, but I do not see any window appearing on the Pi desktop. I will ask Krish the proper fix for this. I then connected my phone using Bluetooth. This did not work at first. After many tries, we tried paring my phone using the settings app. This worked, and after doing so, the bluetooth on the app worked perfectly. This does not make sense, since we are using a Gatt server, rather than anything that requires pairing. This could be because of the Bluetooth code running in the background on the pi. We will talk to Brendan about disabling this, since users should not have to pair their phone to the pi, as this requires looking at the desktop for a pairing code.

During this, Johnny looked at the slots I scored yesterday, and he agreed that they definitely had less room. However, he reassured me that it is definitely not a printing issue, and there must be powder stuck at the bottom. He used pliers to dig them out, and cards are no longer getting stuck in any slots.

After sending an unopened pack shuffle parameter and pressing the start button, the cards began loading as expected. However, the computer vision is reading incorrect values. Right now, the way computer vision works is it is constantly taking pictures and processing them as fast as it can, and the main loop is just taking the most recently processed value. However, this causes pictures to be taken at times where the card is not where it needs to be, and for the main loop to take results from pictures that were taken of other cards. This led to many offset and repeated values. To attempt to test this hypothesis, I added a delay in each card of .5 seconds, and ensured that the reading was different than the last card before firing. This was slightly better, but still not good. It would feed some cards, then reach a point where the timing got off and would act like before. I didn’t really expect this to work, but the fact that it slightly improved things shows me that we need to improve our timing of taking pictures. Taking pictures should be done synchronously, since we want to take one as soon as we can. The currently implemented approach assumed the computer vision algorithm would be extremely fast, so the live value from computer vision would always be what the camera saw. Since this is not the case, we should wait for the ack from the stm (this means feeding is done and next card is on bottom) to take a picture, then process it.

Entry 1: -----------------------------------------------------------------

Date:April 20th

Start Time: 1:30 pm

Duration:2 hours

Implemented dispense offset code.

example3

This immediately solved most dispensing issues. However, sometimes cards are getting stuck in slots. Looking at slots where this happens, it appears that the two sides of the slots are meeting, instead of having a ~3mm distance between them. This could be a printing tolerance issue, or the ends just need to be bent slightly. It’s also possible that there is something stuck at the bottom of the slot. I scored the sides of the wheel on these slots so that Johnny could take a look soon. I found two of them by shining my phone flashlight into each one.

=============== Week 14: =================

Entry 5: -----------------------------------------------------------------

Date:April 18th

Start Time: 1:30 pm

Duration:2 hours

Installing app on my phone. Testing integration. Figuring out why dispensing isn’t good. Ran integration a few times and watch dispensing closely

Sometimes cards do not drop out of slot. Sometimes cards coming up from bottom do not become aligned with slot (when offset = 1240) (slot 7 problem). Sometimes cards coming from top do not slip all the way down.

Solution: go to slightly below slot, then go up. Allows alignment to have bottom of wheel slot aligned with middle of dispense slit, rather than a compromise between coming from below or above. This solves cards coming from bottom not aligned from slot (bc of more aggressive alignment bc don’t have to account for cards coming from above) and cards from top not slipping all the way down because they will always come from the bottom.

Entry 4: -----------------------------------------------------------------

Date:April 16th

Start Time: 5:30 pm

Duration:5 hours

Goal of lab session today is to get cards to feed and dispense in sequence on the actual wheel. Once this is done, we are only waiting on computer vision integration for the whole project to be finished. First I need to figure out why motor movement commands are not working.

I set a breakpoint in the move command, and it does properly call the stepper_set_position_proportional function that I know works. Something about the way I am setting up the wheel must be wrong. To test this, I added “align_to_feed_slot(26)” to the end of the init function to ensure that this did not work. After uploading, it did not.

I am annoyed by having to hold the reset button when uploading, so I will mess with my debugger settings to see if I can fix it. I selected “connect under reset” for reset behavior, and it seems to work more often now.

Since this was working on the breadboard, I know the code should generally be correct. One thing that I changed was moving the homing code into an “ifndef __NO_HOME__” block with a flag from buildflags.h. Something in this block must be necessary. In the block, I simply set the wheel’s speed, then start homing. I moved the setting speed out of this block, and the wheel worked. I removed the align_to_feed_slot function that I added. I believe the problem is that if the speed is 0, the stepper interrupt is never called because the timer’s ARR is 0. This means that proportional code is not able to start moving. To fix this, I added “set_speed(min_speed)” to the function that starts proportional movement.

I set up the second power supply and connected it to the PCB. I tested that the DC motors and stepper worked individually in the same way as the other power supply. Then, I connected both power supplies and turned them on with my laptop not in the system. Then, I plugged in my laptop. The stepper and DC motors worked as before, but they would not work together. The DC motor draw would go too much to one supply, which would drop the voltage and they would move very weakly.

I decided to try using the supplies in series rather than parallel. This would allow me to have both supply output 6V with a current limit of 5A. This would give me a maximum current of 5A rather than the 2A I was getting in series. After hooking this up to the PCB, the stepper and DC motors were able to work at the same time. I realized the feeder shot with way more power in this configuration, and I must have been losing a lot of power before from the 1A current limit. Since this will be even more different on the final power supply, we decided to just try the final power supply before doing more integration.

The power connector wasn’t fitting properly into the PCB. We needed to mess with the pins, and then it worked. Johnny soldered the header on. We then plugged the power supply in, checked very closely for any shorts, and then turned it on very scaredly. It worked and nothing fried. Then, we reattached DC motor and tested them, and they worked. Then, we attached the stepper, and it worked. We tested the integration code that generates a random order instead of using computer vision, and it worked. However, there was some problems with dispensing cards. They would often not fall out, or dispense two. Johnny says that the slot is aligned between two cards, so hopefully this is an alignment issue.

Johnny and I retuned the feeder parameters with the newfound extra power. To prevent having to reset the stm to home the motor (which lost the parameters I updated with commands), I added a HOME_WHEEL command to the stm.

Entry 3: -----------------------------------------------------------------

Date:April 16th

Start Time: 9:30 am

Duration:2 hours

Man lab. Calibrated feeder with new o-rings and front motor closer to front. Much, much more consistent.

Entry 2: -----------------------------------------------------------------

Date:April 15th

Start Time: 5:30 pm

Duration:4 hours

Got sstepper and servo working on new PCB. Tested the new gate Johnny printed. It fed cards well, but there was a lot of friction.

Entry 1: -----------------------------------------------------------------

Date:April 12th

Start Time: 3:45 pm

Duration:4 hours

Johnny is ready to test the card feeder. I want to test all of my calibration commands to greatly speed up testing. I will test each command in a row. I need to rewire the uart connection.

example3

The stm was not reading parameters properly. I realized my read_params function overwrote the uart buffer with its logging, which changed the state of the uart buffer for the calling function. After fixing this, parameters were read correctly.

Testing sending numbers over 4 bytes, and it worked.

Using these calibration commands, we tested some different card feeding techniques. My initial design that would send the front motor forward, then start sending the back motor backwards was clearly not going to cut it. We first tried sending both motors forward, then sending them backwards slightly, then running them in opposite directions. This did not work. Next we tried running the rear motor backwards slowly all of the time, and shooting the front motor forward to feed a card. This did not work, since the front motor was not able to overpower the rear wheel. Finally, we tried moving the cards backward to ensure they are in a consistent spot, then moving both motors forward to get full power, delaying slightly, then sending them in opposite directions. This was the most promising, but cards would often not completely leave the feeder. We determined this meant we need the front motor to be closer to the edge, since right now the front motor has no control over the cards that have passed it, but not left the feeder. We also decided to switch to o-rings for more consistent feeding.

=============== Week 13: =================

Entry 5: -----------------------------------------------------------------

Date:April 10th

Start Time: 11 pm

Duration:1.5 hours

Wrote handlers for commands. Couldn’t ssh to pi. Need to add command to set offsets for feeder and dispenser. Need to update pi code to include these new commands in enum once they exist. Also need to have pi interpret uart as ascii. These are the commands. I will test them tomorrow. I also need to finish the calibration script on the pi.

example3 example3 example3 example3

Entry 4: -----------------------------------------------------------------

Date:April 10th

Start Time: 3 pm

Duration:4 hours

Brendan is soldering a pin header onto the homing sensor PCB. Testing it with the multimeter and the power supply supplying 3.3V, it did not work as intended. Referring to the wiring set up on the breadboard and the breakout’s schematic, I realized the photointerrupter was oriented the wrong way on the breadboard. We used chipquick to desolder it, and we decided to trash the pcb and use a new one, since it would be difficult to resolder and the plastic pin sockets melted.

After soldering the new breakout board and testing with the multimeter, it did work as intended. Now attaching it to the PCB and adding homing to the test code that aligns to a series of slots. This works as intended.

We are intending to get checkoffs for UART and stepper motor before class. I wired up UART so that we could.

We asked Shivam for preliminary PSDR checkoffs. He said he would prefer to see them without the STLink connected to provide power. I used the 6V channel on the power supply to provide 3.3V to the microcontroller, and the 12V channel to provide 12V to the stepper. This worked as intended. Shivam came over for checkoffs, and everything went well, except the pi was not receiving UART commands from the Pi. I realized we did not ground the two boards together, and it worked after fixing this. Brendan also set up a test script as a cron job to get the pi to trigger the stm after a power cycle.

Next, we test the servo. We wired it up without soldering anything. It worked. We then attached it to the gate, and saw if the wheel could smoothly rotate with the gate closed. We used the servo calibration script I wrote before. We determined the angle of the servo should be 5 to press against the wheel just enough to the servo is always pushing, but not over exerting itself to the point that it is loud. Running the wheel with the gate at this angle, the cards sometimes get slightly stuck, but not enough for the stepper motor to skip. This may be a mechanical issue that needs to be changed.

We tried testing dispensing from certain slots using the gate, but we will need a more precise homing and dispense offset system, since we currently can’t guarantee the card aligns with the slot. We decided that will try this again once we have the servo systems soldered, since the connections were very janky.

I began writing code for the calibration related commands on the stm32, since we are reaching the point where we need calibration to be easy and fast. I wrote this function to receive a certain number of parameters for the command:

example3

I also had to write short functions in the stepper and wheel libraries to move a certain amount of steps / degrees.

I will finish writing these functions later, then test them on saturday when we meet. One capacitor pad got ripped whil brendan and krish were soldering, so I cannot use the PCB currently to test. I need to use the breadboard.

I am starting to write the calibration code on the pi. First, iterate over each command in the enum, and print each’s name and value. The plan is to have two threads: one for sending commands that the user types, and one for printing everything that the pi receives from the pi, such as “” when it is expected parameters.

Entry 3: -----------------------------------------------------------------

Date:April 9th

Start Time: 7:30 pm

Duration: 5.5 hours

Meeting to start soldering and testing subsystems on the PCB. First we will test UART connections without soldering. The fourth pin on the pi is the TX, and the 5th is the RX. On the PCB, the pins are opposite. We connected the wires from the breadboard and propped them in the PCB. I ran the test UART code I wrote earlier on the stm that reads a UART signal from the Pi, and then responds with the same. This initially did not work. I realized I need to connect the grounds, so I connected the ground of the PCB to the ground rail of the breadboard that the pi is connected to.

Next we will work on getting the DC motors working. First we tried using the DC driver without soldering, since the pins appear to press against the metal contacts of the PCB. We connected a motor to the bottom jumper on the PCB, and checking the PCB, this is connected to PA4, 5, and 9. I changed the configuration of the test code to align with this. After uploading test code, the motor did not move. Using the multimeter to check signals. We have a test pad for the pwm, and it is outputting the proper signal. We measured the 5V pin on the chip, and it is reading 0. However, the 5V pad that it appears to be contacting is measuring 5V. We decided to solder the driver.

After soldering, the STM is not allowing me to upload code. I am getting an error that the GDB server is unable to start. The PWM test pad is still outputting the proper voltage, and the 5V pin is now powered, however the motor is not moving. We disconnected the 5V power and powered the PCB back on, and realized the 5V led was turning on while the PWM for the motors is wrong. It seems like there may be a short between the PWM line and the 5V line. We will check for a short with the multimeter. The multimeter is beeping for conductivity, but this does not necessarily mean there is a short, since the resistance value does appear fairly high. Since the programmer and 5V / PWM issues were not occurring before soldering, we decided to desolder the IC while johnny collects a print from Bechtel.

After Johnny left, we decided to give it one last try with 5V connected, since we realized that the PWM pin was still working, which would not be the case if it was truly shorting to 5V. Turning it on this way, we saw that the 5V level was stable (instead of pwm like before) and the PWM worked perfectly independently. We listened closely to the motor, and realized it was whining, meaning the wiring was correct, but we didn’t have a high enough duty cycle for the motor to move. We upped the duty cycle, and the motor moved. This was a big relief, since it meant our PCB wasn’t short circuiting. Because of this, I double checked my programmer issue, and turned off logging to file. After doing this, everything worked again, which is another relief.

Next we decided to solder the USB C connector that will be used to power the Pi. Krish is attempting solder it by hand, then we will try solder paste if it does not work out. Two of the pins were bridged, and we have spent a long time trying to unconnect them. We decided to remove the port completely and try again. We used chip quick and the heat gun to remove the connector, but one of the ground pads was removed. This shouldn’t be an issue, since it is just connected to the shield, which is connected to other ground pins anyway. Brendan arrived in lab and attempted to solder the USB C, then Krish took back over, and it was successful. Powering on and reading the voltage on the USB, it reads 5V.

Next we will get the stepper motor working. While waiting for Krish to solder the whole thing, I will work on other homework. He consulted me about the capacitors we are using and which way they should be oriented. Once he finished soldering, we set up the power supply on the 12V pin. I double checked the pin header for the stepper motor, and realized it was incorrect. The middle two pins were switched. This is my fault, since it is the order I told him to use. This is fine anyway, since there are wires between the stepper and the PCB that I changed the order of. After switching these and programming the test code, the stepper successfully oriented to 180 degrees, then 0. However, it was shaking a lot whenever it moved. I reduced the minimum speed to .05 rotations per second instead of .5, and this completely smoothed the motion. I wrote test code to move it to a sequence of slots, and this worked successfully.

example3

Next, we will get preliminary checkoffs, solder a header to the homing sensor and ensure this works, then get the servo working. I also want to get all the calibration scripts and commands set up.

Entry 2: -----------------------------------------------------------------

Date:April 9th

Start Time: 9:30 am

Duration:2 hours

Setting up ST Link on PCB. Writing test code for blinking extra GPIO B6 so we can check that code works with multimeter. Testing that the labels on the stlink aligned with where 3.3V and ground are correct. They were. Then connected each pin of the header to the stlink and plugged it in. When trying to upload test code, cube ide complained that I need to update st-link firmware. After doing this and trying again, the st-link said that it did not detect a device. I then broke out the 3.3v and gnd signals from the st-link while they were plugged into the PCB, and they were reading a 3.3v signal. I then probed a part of the PCB that should be connected to the 3.3v ground plane, and it was reading 100mV. Also, the 3.3v LED did not turn on. Somehow the 3.3V plane is not being powered. We have a schottky diode between the programming header 3.3V and the ground plane. It seems like this is the problem, since it is receiving 3.3V on one side and 100mV on the other, rather than 3.3V like we would expect. Checking the orientation of the diode, and it looks correct. For now, we will short this connection to see if the schottky diode is the problem. If it is, we will try it with another diode. If this doesn’t work, we will need to analyze our diodes to make sure we ordered the correct ones.

Krish resoldered the diode because the connection looked loose. Nothing changed. Now trying with shorted connection. This got further in the process, but it said the stm was in reset mode. This means the other diode is shorting the reset pin to ground. We removed this diode. The st link was then able to flash the microcontroller, and the blinking voltage code worked!

Next we will continue to solder and test subsystems on the PCB.

Entry 1: -----------------------------------------------------------------

Date:April 5th

Start Time: 1 pm

Duration:5 hours

I have decided to use a more interrupt-based approach rather than explicitly handling the UART sequence in the start button’s interrupt handler. I will change all UART reception to happen asynchronously, and the main loop will simply check if UART reception has occurred. The EXTI interrupt will set a flag that will be handled in the main loop. When there are no interrupts, the main loop will enter sleep mode. This is a much more robust way of handling things. I will need to write a UART driver.

The uart driver will store the data in a ring buffer in the background. It will also keep track of the beginning and end of the range of data. If the ring buffer overflows, the data should not be written to the buffer. The interface should have a way to indicate whether the buffer is empty and a way to read a certain amount of bytes from the buffer.

I am using the HAL_UART_Receive_IT function to set up the interrupt on the uart, then using the RX_Complete callback function to manage the ring buffer.

The interrupt is not triggering when testing with the terminal emulator, even the UART_2 interrupt from the HAL. After reviewing the UART register values, they all look correct. Maybe my terminal emulator is not properly sending signals. I will try the interrupt from the pi. This worked properly.

I rewrote the main logic on the stm:

example3

I realized while debugging that the stm uart was always receiving zeros whenever the pi would send. Looking into the pi’s main code, I realized I was sending bytes wrong. The send function for uart expects a byte object, but I was feeding int objects without casting them. I forgot to properly port over the code from my working send_commands function. Once fixing this and using the new main code, the pi’s main.py file successfully sent and received acks for each feed slot. Once starting unload, it hangs after the second slot. This was another error in the main.py script.

I decided to add more to the stm.py file to simplify sending commands as well as receiving with no timeout. I will create an STM class that extends Serial and adds extra functionality.

example3

After fixing this and turning on the power supply, the control code fully works as expected. After the stepper motor homes and the start button is pressed, the stepper motor moves to each slot, then waits for the motors to fire the card, then moves to the following slot. Once all slots are “filled”, it switches to unloading. The servo will close, then the stepper will move to the proper slot, then the servo will open, repeated for all cards. We will definitely need a delay for the servo to close before the stepper starts moving again, which may not be insignificant for our total shuffling time. It may be worthwhile to research a faster servo, since this will be a bottleneck in our shuffling time.

The next item on the checklist is to add the stepper enable signal. I will add a 4.7k pull up resistor and a connection to C9 to align with the PCB. This pin should be set to be open drain, and be 1 when the stepper is disabled, and be 0 when the stepper is enabled. After adding stepper_enable, stepper_disable, wheel_enable, and wheel_disable functions, they work as intended. By default, the stepper is enabled. It will be able to be disabled from a command from the pi.

I just realized that if the shuffler is turned on with the stepper in a position between the photointerrupter but not in the expected home position, the offsets will not be accurate. I need to edit the stepper library to only consider the motor homed if it sees a high signal from the sensor after seeing a low signal:

example3

The next step is to rewire and remap all signals to match the PCB. I have already done this for the stepper. These are the mappings I must change:

example3

Since the DC motors and servo motors need a different PWM frequency, I cannot use the same timer for them. I will instead connect the servo PWM to an extra GPIO. PB5 works perfectly, because it is connected to TIM3 ch2, which is already what the servo is running on in software.

The DC motors PWM are connected to the proper pins, but the dir outputs are not. I will fix this now in the code and wiring. The front motor works as expected.

I rewired the servo and changed the stm configuration to use PB5, and it works as expected.

I rewired the UART to the pi and change the stm configuration. I also created a serial_send function so that I didn’t have to use the HAL function directly in my smart_card_shuffler.c.

I tried using the other, smaller servo we have at the station. It moves much faster, and did not have any glitchy behavior. I think we should switch to a faster servo, because the speed of opening/closing the gate will be a large bottleneck, and the unpredictable movements this one makes could cause damage.

The next steps are to ensure the error and reset commands/control flow is properly working. If they are, the software is fully hypothetically working. However, I still need to implement the extra calibration functions and write scripts on the pi to make use of them. I will also need to ensure all of the subcomponent tests I wrote before still work and are suitable to test submodules of the pcb as we solder it.

=============== Week 12: =================

Entry 4: -----------------------------------------------------------------

Date:April 4th

Start Time: 1 pm

Duration:5 hours

In the lab, starting on checklist I created yesterday. First, I need to test loading / unloading over UART. I used the calibrate servo script I made before on the pi that sends integers you type over UART. After fixing some conflicting definitions in my #include setup (made weird by autogenerating code with the HAL and writing a library using global variables on the stack), this worked as expected. I set the initial state to load, and when I sent a slot number over uart, the stepper would align to that slot, then the DC motor would move as though it was feeding a card. When I sent the START_UNLOAD command and continued sending numbers, the stepper would align the other side to that slot, and the servo would open and close the gate. Next is to finish main sequence logic start to finish not including button. This is already set up including error command, requesting ready signals, and a finish command after unloading is complete.

Next, I need to set up the start button. On the PCB, it is connected to C1. However, this is currently the stepper motor’s dir output. I will remap and rewire the stepper outputs to it’s proper GPIO ports, B13 for dir and B14 for step. This worked exactly as before.

The button will trigger an interrupt. If the shuffler state == READY, change the shuffler state to SENT_READY, then send a start signal over UART, then receive with a timeout. If something other than an acknowledgement of START is received, the command should be processed, then reception should be retried. Once a timeout happens, set the state back to ready. This would be a good time to flash an indicator on the RGB LED. This prevents initialization or calibration commands being missed while waiting for ready ACK. If an ACK is received, move to load state.

I set up C1 to be connected to EXTI1 and trigger an interrupt, and unmasked the interrupt in the NVIC. I wired up the button with a pull down resistor. After reading the GPIO HAL file, I found the callback function I needed to define is HAL_GPIO_EXTI_Callback. I set a breakpoint at this function and went into debug mode, and the callback function was successfully called.

This is the callback function:

example3

Next, I will update the main python script logic on the pi. The pi should wait until it receives data from the mobile app, then wait for a start signal from the stm. Once a start signal is received, it will respond by acknowledging the start signal. Next, it will send the start load signal. Next, it will send the values of all 52 slots and record their values in a dictionary. For now, this will be simulated because computer vision is not set up. Then, it will send the values of each dispense slot in order. Finally, it will send a finish signal.

I created an enum in python using the enum library for the commands:

example3

The rest of the commands align with the stm.

I need a way to substitute the computer vision providing the starting card order. I wrote this function to generate a random order:

example3

I was encountering many errors where I would use the wrong variable name or something similar, so I set up vscode ssh server on the pi so that I could use vscode and python intellisense.

I was able to ssh in from vscode, but it seems like I need to do more work to set up the language server for autocomplete, so I will ignore this for now.

I am having trouble with the button. It seems like the stm is sending many start signals in a row, possibly because the UART is busy. I tried aborting the current UART transfer to see if that solves the issue, but it did not. I will set up the UART that is connected to the usb on the NUCLEO board so I can use print statements to see real time logging.

Based on the ioc, this is PA2 and PA3. Based on the datasheet, this corresponds to usart2. I set this up, then set up PUTTY on my computer to communicate as a serial monitor. All calls to send on uart2 is wrapped in an ifdef __USB__, which I added to buildflags. I also added an include stdio.h within this same guard so I could print to uart. I monitored the serial port using PUTTY. I had to enable the option to add a carriage return to reach line feed.

Based on the output logs, the stm is sending the start signal, then trying to receive a lot, and recognizing itself as receiving a bunch of zeros. Next, I will check if the pi is actually sending this many zeros. If it is not, I will rethink my approach to this asynchronous process.

This is current progress on the main pi code:

example3 example3

Entry 3: -----------------------------------------------------------------

Date:April 3rd

Start Time: 8 pm

Duration:3 hours

Now testing the wrapper functions I wrote yesterday. One major change I need to make is deciding how to handle the interrupt call back functions in my wrappers. I decided to treat it the same way as my other wrappers, and have it be the caller’s responsibility to call the interrupt handlers that the library provides in its timer callback functions. I updated the wheel and card_feeder wrappers to include interrupt handlers that call each of their motor’s interrupt handlers.

First, I will test the wheel wrapper. It seemed to work fine, but there was a strange issue with the stepper when setting it to align with slot 0 immediately after homing. It did a full rotation. After running through the code with the debugger, I realized the stepper interrupt was toggling the step output and adjust position before checking if the target position had already been reached.

example3

This caused it to do a full rotation when targeting its current position. I switched the order of these two actions, which solved the problem. I set the feed offset to 90 degrees and the dispense offset to 270 degrees, then aligned to each slot for feeding and dispensing, and this worked as intended. The stepper moved to the feed offset for slot 0, then made 51 slight increments. It then did the same thing at the dispense offset. I tried running this with the wheel on, but the current slack in the print makes it not work properly.

Next I will test the card feeder wrapper. This should make the motor that is current wired run according the the front motor parameters, and also output new PWM and gpio signals for the speed and dir of the rear motor on A10, A15, and A4 according to the rear motor parameters. I hooked up the AD2 to read these signals, and they were correct. A15/A4 would be high while the other is low (depending on direction), and they would only be high for the duration specified in the parameters. The PWM would also only be active during this time, and at the proper speed.

The card gate wrapper also worked as expected. It opened and closed the gate depending on the open and close positions it was initialized with.

Now I will plan out the state machine and final code. Once this is done, I will remap and rewire all GPIO pins to their configuration on the PCB so that the code will be the same. For this I also need to consider the pull-up resistor on the enable pin of the stepper motor.

I extended gate.h to allow for more calibration, including a gate_drop_card function that uses a new struct field drop_delay to open the gate, wait a certain period, then close the gate.

I planned out all the commands I wish to be available for the stm to follow. These will be useful for calibration, as well as if we want to store configuration values on the pi that we can send to the stm on startup. 0-51 will represent slot numbers, and the stm will load or unload that slot depending on its state. 52 and above represents commands used in the main flow of the program. After COMMAND_CUTOFF, other commands can be used that can contain a second batch of data with a variable amount of parameters. These will be used for testing, calibration, or setup.

example3 example3 example3

I began writing the logic for processing commands, especially in the main loop. This will be slightly different once I add the start button, which will be handled in an interrupt to send a UART signal to the pi, then wait to receive a signal using a timeout. I also want to set up my UART to be interrupt based to reduce polling, especially when the stm is idle.

example3 example3 example3 example3

My next step is to write a test script on the pi to test feed_slot and dispense_slot being called over UART. I will need to have the initial state of the STM be LOAD for this, since I do not have the button set up. Once I can go through a full sequence like this, I will set up the button and its interrupt handler, including using an interrupt for the UART. Then, I will add the enable signal and functionality to the stepper and wheel drivers. Then, I will remap all of the signals to their GPIO values on the PCB. Then, I will handle the error command and reset_shuffler function. Once all of this is complete, the software would technically work on the final PCB for its final function. I will then implement all of the extra commands and write scripts on the pi to help with calibration. The pi calibration scripts will save the calibrated values to a file, which will be read on startup of the main pi script and sent to the stm once it is ready.

Entry 2: -----------------------------------------------------------------

Date:April 2nd

Start Time: 4 pm

Duration:2 hours

I have these calibration functions in mind / commands to obey by:

example3 example3

I wrote wrapper libraries and test functions for wheel, card feeder, and card gate. These are the header files, each function is a fairly simple wrapper of the motor libraries. I am away from the lab, so I will need to test these wrappers tomorrow.

example3 example3 example3

Entry 1: -----------------------------------------------------------------

Date:April 2nd

Start Time: 9:30 am

Duration:3 hours

Mandatory lab. Communicating signals with Brandon. STM will send a ready signal when the button is pressed, and Pi will send a start load signal if a configuration has been sent from the mobile app. If not, the stm should reset state after a delay. Then, the pi will send a number for load, and the stm will complete the load and respond with the same slot number. Once all cards are loaded, Pi will send a start unload signal. It will repeat the same process with the numbers. Then the pi will send an end signal. At any point, either device can send an error code that resets the state and disables the stepper.

Need to troubleshoot stepper. First going to analyze code via signals coming out of stm. They look correct. The step during homing is at 300hz. At 200 steps and 16 microstepping, this is 1 rotation every 10 seconds. This is the speed I set it to in the code. I set the Vref on the stepper driver to 800 mV, and the stepper is working. It is drawing 200mA when the stepper is moving, and 70mA when idle.

I will now try running the stepper with the DC motor driver wired up. First I need to rewire the DC motor and make sure it works. Running the stepper motor test code that homes the motor, then turns 180 degrees twice works fine even with the DC motor connected. However, if I run the DC motor code after this, the DC motor works, but the stepper motor driver starts drawing lots of current.

After testing the DC motor at different speeds, it seems like the problem was the startup current from the DC motor. It was causing the power supply to reach its current limit, which dipped the power supply’s voltage. When the voltage of the stepper driver dipped, it caused a problem which made it draw lots of current. This would be a massive problem if it occurs on the final design, so I want to find a way to reduce this. However, since the power supply is much stronger, the voltage drop should not be significant.

When running the bench power supply with a current limit of 1A, I am able to power the DC motor at 100% while the stepper motor is idle with no issues. I am worried about being able to power both motors at the same time. I will run the DC motor with a current limit of 1A - 300mA (approximate maximum current of stepper) and see if the current limit is hit. It is, so I do not feel comfortable running the stepper motor and DC motor at the same time, since it might cause the brownout in the stepper driver that causes it to draw lots of current and fry our stepper motor driver. It may be worth adding a fuse to prevent this. I will try adding a capacitor across the DC motor driver to see if this makes a difference. It does seem to limit the peak of the current draw. I added a 100uF capacitor across the power leads. This would easily be fly wireable on the PCB due to the form factor of the motor driver. I was able to run the DC motor at 700mA while the stepper motor was idle. I will now try running them both at the same time with a 1A current limit.

With the motor running at 70% and the stepper motor already moving, it works.

With the motor running at 70% and starting at the same time as the stepper motor, it works.

With the motor running at 100% and starting at the same time as the stepper motor, it works.

Now the servo, stepper, and DC motor can run at the same time, since the servo will not affect the current limit of the power supply since its running off my laptop. I will return to the lab later to start writing all of the wrappers and integration code. One thing to note is the stepper will need to draw more current when moving the wheel. When testing full integration, I will use a second benchtop power supply to focus on powering the stepper.

=============== Week 11: =================

Entry 4: -----------------------------------------------------------------

Date: March 27th

Start Time: 5:30 pm

Duration:2 hours

Before class, cleaned up lab station so there is no more packaging garbage or tools that we do no not need. Also helped assemble servo motor housing in trapdoor. Fixed servo driver to also contain the ccr register number in the struct and use this when adjusting PWM output. Noticed some strange unpredictable servo behavior. After hooking up the AD2, I confirmed that the PWM output going to the servo is correct according to the data sheet. The behavior seems to occur when restarting the servo and immediately trying to set its position to the same position it was in before losing signal. When writing new positions, it works better, but there is still some jittering. I may try using a higher PWM frequency and see how this improves / worsens the condition. I adjusted the timer ARR to 20000, since I knew the maximum pulse for the PWM sets the CCR to somewhere around 8500. There is now no jittering.

I decided to create a servo calibration script to examine how different positions appear in real life. I wrote a short script on the pi:

example3

And the stm:

example3

I will now try running the servo motor, DC and UART at the same time.

example3

This worked as expected after fixing the connection quality of the DC motor in the breadboard. I will now try the refactored stepper motor code. It does not work. After running the debugger, I see the micro is hitting a hard fault. I never assigned a value to stepper->htim and I try to dereference it, so it is segfaulting. After fixing this, the stepper is still not moving, and the power supply is hitting the voltage limit when turning on the stepper. Next I will examine the step and dir outputs with the AD2 to make sure the code is working, then fix the wiring and see if the problem is related to the DC motor and stepper both being connected to 12V. If it is, I will try adding a decoupling capacitor across the power supply of the l293d. Once the stepper motor is working on its own, I will write code that integrates it with the other motors. Then, I will finish the wheel wrapper and write calibration scripts to find the feeder and dispenser offsets.

Entry 3: -----------------------------------------------------------------

Date: March 26th

Start Time: 5:30 pm

Duration:0.5 hours

Getting started on refactoring stepper motor driver. I replaced all addresses of registered passed with the handle to the peripheral they belong to. I then changed all references to registers in the source file with traversing the handle. I repeated this for the servo driver.

Entry 2: -----------------------------------------------------------------

Date: March 26th

Start Time: 9:30 am

Duration:2 hours

Mandatory lab. Since the PWM and direction outputs are working, I decided to wire up the l293d on the breadboard. Here is a photo of the final wiring:

example3

I used drivers 3 and 4 on the driver. Before I hooked up the motor, I set the motor voltage to 5V and measured the output with the AD2. Running it clockwise resulted in a +5V pwm signal for 5 seconds, and running it counterclockwise resulted in a -5V pwm signal for 5 seconds. I then connected the motor and ran the power supply at 12 volts. The motor still did not move. I tested the motor at 100% duty cycle, and it ran at full speed. I tested different duty cycles, and found that it would not work below 65% duty cycle. I will not hard code this into the driver, since it may be different for the final motor and I would like to have access to the entire PWM range. Now I will set up UART communication. Brendan set up the wiring for UART to PC10 and PC11. Based on cube IDE, this could be UART 4 or USART 3. I will use USART 3. I am rewriting these drivers compared to Brendan’s because he is using a different laptop since he revived the one that died, and it should not take long.

I simply enabled USART 3 in the ioc file and configured PC10 and 11. I then wrote this code in the main file:

example3

I then connected to the pi by ssh and ran Brendan’s test UART code and it worked fine. For the first iteration of the stm code, I will simply receive/send UART without interrupts, since the pi will wait for a ready signal from the stm before sending commands. The stm will wait to send the ready signal until it is at the point where it can block for a UART reception. In the future, the stm will respond instantly to each

Looking at Brandon’s integration code for the pi, the pi will be sending a numbers 1 through 52 to tell the pi which slot to feed into. Then the pi will send a command to switch to dispensing, and send numbers 1 through 52 in a different order. On the stm side, I should do some processing for when cards are back to back to allow the cards to fall without engaging/disengaging the servo.

Next I will rework the stepper driver to take in handles instead of register addresses, and finish the wheel, shooter, and dispenser wrappers for the motors. Then I will write logic in the main loop to process commands from the pi.

Entry 1: -----------------------------------------------------------------

Date: March 25th

Start Time: 3:30 pm

Duration:2 hours

I need to get the DC motor drivers working, then work on command interpretation and integration between all the motors. Looking at the HAL interrupt, it indicates which channel was triggered by setting the channel field in the timer handle. This has fully convinced me to rework the driver to take the timer handle instead of each individual register, since the timer structs’s address is accessible through the handle.

After changing this, the struct is much simpler:

example3

I went through the source file and replaced every reference of a register to traverse the handle to get to that register. This was difficult for the CCRx registers, since you needed to traverse differently depending on the channel number you were adjusting. This is what the CMSIS timer handle looks like (which is the Instance field of the HAL timer handle):

example3

We want the (12 + channel number)th element in this struct. First, I tried indexing into the struct like an array, but this is not valid c. For some reason I remember this being possible. Instead, I need to find the exact address and dereference this pointer. First, I added 0x30 + 4 * channel number. This did not work, since adding 1 to a pointer variable adds the size of the variable rather than 1, so it was adding 0x30 + 4 * channel entire TIM_TypeDef sizes. Instead, I needed to first cast the pointer to a uint32_t pointer, then add 12 + channel, then dereference. This works. My PWM output now works as expected once again.

example3

I then updated the interrupt handler to consider this new Channel field that we have access to. Since we are storing the channel number in the struct and the HAL uses an enumerator with named channels, we need to map the numbers. I did this with a look up table.

example3

This is necessary because these values are not 1->4. This is the new interrupt handler:

example3

I also turned off the PWM output in disable_motor to reduce noise caused by PWM while the motors are disabled.

=============== Week 9: =================

Entry 4: -----------------------------------------------------------------

Date: March 13th

Start Time: 3:00 pm

Duration: 1.5 hours

Before entering lab, researching why interrupt isn’t happening. Realised didn’t set CC1IE in the timer’s DIER. I may have to use this as the enable / disable of the interrupt in the library if the output enable doesn’t work, since the output enable may be controlling the GPIO output. I will test if this works before changing this. The physical library will work, but more interrupts will be called then necessary if this doesn’t work. Will test once I am in lab. Johnny also wants me to take a picture of the footprint verification, so I will need to ask a ta for a stm with the same size. If there is no ta, I will take a picture with everything other than the stm, since the size matches the discovery board.

I got an stm with the same size and compared the footprint verification, took a picture, and sent it in the email chain.

example3

Checking the interrupts, the interrupt is being called, but the motor is not being disabled. It seems that the flag indicating which channel was called is cleared by the HAL before the handler is called. I am tempted to edit the HAL to clear the flag after calling the handler rather than before, because I need to know which motor needs to be disabled. I will think about how to test this without using the flag.

Entry 3: -----------------------------------------------------------------

Date: March 12th

Start Time: 3:00 pm

Duration: 30 minutes

An issue was brought up in our PCB / schematic review from the TAs in the stepper motor wiring. Johnny asked we what it should be, and I updated my local copy of the schematic and sent him a screenshot. The IO power input should be 3.3V, and the motor power input should be 12V with capacitors to ground.

example3

Entry 2: -----------------------------------------------------------------

Date: March 12th

Start Time: 9:30 am

Duration: 3 hours

Mandatory lab. Goal is to get DC motor driver working and review schematic. I noticed the ATX connector jumps the necessary pins with a resistor. I tested this on the real power supply, and it did not properly powered on. I asked Johnny to remove the resistor. I also confirmed with the L293d datasheet that 3.3v signal levels are acceptable. I then continued work on the DC motor driver. I completed the interrupt handler, helper functions for enabling / disabling the motors and setting speed, and functions to run the motors for a certain length of time.

When starting the motors, the ARR of the PWM is set to an appropriate value between 0 and 100. ARR = speed. This results in a longer PWM pulse for faster speeds. To enable the motor, I set the bit in the struct and enable the output compare for the appropriate channel of the wait timer. When disabling the motor, the opposite is done. This ensures the interrupt handler is not called unnecessarily. When setting the motor at a certain speed, the PWM CCRx register is set, the direction GPIO pins are set, and the motor is enabled. To wait for the motor is finished, await_motor is called, which waits for interrupt until the enable flag in the struct is false.

I then configured the output pins for the motor. I did not use the schematic values of A4 and A5 because A4 is not exposed on the Nucleo. I will use A6 and A7 instead. The PWM will use the same pin as the schematic, PA9 (TIM1 Channel 2).

I wrote test code using the library:

example3

After wiring the circuit, the PWM appears to be outputting properly:

example3

The direction outputs also work correctly. However, the interrupt for the output compare is never being called. CCR1 and CNT are being set to appropriate value. The CCER was not being set properly. However, the CCMRx also needs to be set properly. I assumed this would be set by the IOC. Checking the IOC, I realized I had the channels in frozen mode, rather than active. The global timer 4 interrupt wasn’t enabled in NVIC.

After changing this, all registers seem to be set to the proper value, but the callback I used from the HAL is not being called. I need to do research on how to use OC using the HAL. I also wonder if some HAL struct values are not being properly set for my callback handler to be called because I am directly changing register values rather than using the HAL.

I just realized that I can use the CMSIS timer handler (TIM_TypeDef) type to pass to the init function and struct rather than passing each address individually. This will save lots of annoying code for all of my drivers. I would like to rewrite all of them this way eventually.

Entry 1: -----------------------------------------------------------------

Date: March 11th

Start Time: 3:30 pm

Duration: 1 hour

Working on DC motor drivers. The driver will need to enable / disable motors and run them at a certain speed for a certain length of time. To control speed, a timer will need to be configured for PWM output. To control length of time, another timer will need to be configured to trigger interrupts after a certain length of time. For this purpose, I will use two channels of a timer set to output compare no output. For the other purpose, I will use the PWM outputs used on the schematic, which are PA9 and PA10. This corresponds to TIM1 channels 2 and 3. I want to be able to set the CCRx to values 0 to 100 to control speed, where 1 is fastest, 100 is slowest, and 0 is off. This means the ARR will be 100. The datasheet of the motor driver has a test circuit where the PWM frequency is 5kHz. I will use this value. I will need to set the prescaler to 166 to achieve this. (84000000 / (100 + 1)) / (166 + 1) = 5000.

For the other timer, I will use timer 4. I want to be able to easily set times. I will have the ARR value of 65535 correspond to 65.535 seconds, so the length of timer being on is accurate to the millisecond. This would require the prescaler to be 84000 - 1 so that the CNT increases at 1kHz. However, 84000 - 1 would require a >16 bit value, and TIM4’s prescaler is 16bits. I will instead use 84000 / 2 = 42000 so that we have accuracy within 2 ms. Times will have to be multiplied by two when being entered into the CCRx registers. The channels will be configured as output compare no output so they can trigger interrupts to turn the motors off. When waiting for a time, I will calculate the value the timer counter will be after that many milliseconds. I will set the output compare register to that value. The interrupt will detect which is high, acknowledge the interrupt, and turn the appropriate motors off.

=============== Week 8: =================

Entry 6: -----------------------------------------------------------------

Date: March 6th

Start Time: 9:00 pm

Duration: 3 hours

Wrapping up slideshow for tomorrow’s presentation. Added stepper motor driver slide to the major components section. Added mounting holes to photointerrupter breakout, and added slides with screenshots of schematic and PCB for the breakout to the slideshow. Updated functionality status screenshots to more accurately reflect Krish and Brendan’s work. Final PCB:

example3 example3

I also printed out layouts for both PCBs for footprint verification.

Entry 5: -----------------------------------------------------------------

Date: March 6th

Start Time: 3:30 pm

Duration: 2 hours

Discussing PCB and slideshow. My PCB needs mounting holes, and there are some additional changes to be made to diagram. I got videos of stepper and servo motor working. I realized the servo motor is quite slow. Since we don’t need it to move much, this should be ok. If it is not, we will replace it with a lower torque servo or increase the size of the gear. I changed the servo library to work with the new servo. It needs to output a range of 500-2500us pulses, and the angle range is 270 degrees. Based on the calculations from earlier, I determined the ARR should be between 1639 and 8192.

Entry 4: -----------------------------------------------------------------

Date: March 5th

Start Time: 9:30 pm

Duration: 2 hours

I finished the breakout PCB for the photointerrupter. I will show it to the group tomorrow to receive feedback. I also updated the servo motor slides, some software progress slides, and the functional block diagram based on group feedback.

Entry 3: -----------------------------------------------------------------

Date: March 5th

Start Time: 10:30 am

Duration: 2 hours

Sitting down during manlab hours to work on presentation. I received feedback on my diagrams, and updated them appropriately. Tonight, we will upload all documents, make changes to slides to add more major components and videos, and I will finish the breakout PCB.

Entry 2: -----------------------------------------------------------------

Date: March 4th

Start Time: 8:30 pm

Duration: 2 hours

Back at dorm, continuing work on presentation. Finished block diagram by adding power network. Creating software capabilities chart showing which parts of each software component have been completed. I also planned out the prototyping section to accurately fit the prompt, especially showing which portions have been proven to work and which have not.

Entry 1: -----------------------------------------------------------------

Date: March 4th

Start Time: 4:30 pm

Duration: 2 hours

Sitting down to work on presentation. Brendan, Krish, and I went through the presentation sections and determined what needs work. I decided to make the functional block diagram and new diagrams for the software development progress. I also agreed to get videos of prototypes that I have working. If I have time, I will get the DC motor driver prototyping working as well so I can present this. I finished all of the functional block diagram besides power.

=============== Week 7: =================

Entry 4: -----------------------------------------------------------------

Date: February 27th

Start Time: 5:30 pm

Duration: 3.25 hours

We sat down to ensure our schematic looks good before Johnny moves onto PCB design. After reviewing as a group, these were our action items:

  • check diodes are right kind / right place
  • check crystal oscillator values
  • update stepper motor driver wiring
  • bottom pdn and CLK should still be connected to +3.3v
  • UART resistors / diodes
  • change motor driver for both directions

After reviewing lecture notes, we determined that we are not using the right kind of diodes and are positioning them incorrectly. Secondly, I checked what crystal oscillator is on the STM32 and determined that no HSE is used, instead the HSI 16MHz oscillator is used. There is a low speed external (LSE) oscillator for real time clock, but we do not need this. We will use the HSI clock for our final project.

We considered having protection for UART signals in the form of diodes or current limiting resistors. I did not do any research into this, but it should be okay to directly connect the signals. Johnny may research this as he designs, and we can ask the TAs for advice as well. Johnny changed his wiring of the motor drivers so that we can control the motors in both directions with just one PWM signal per motor.

Next, I sent Johnny the final wiring of the stepper motor driver based on my testing yesterday and today. Enable is grounded (in final design should be connected to GPIO with external pull up resistor), MS1 and MS2 and connected to +3V, RX/TX (PDN) are floating, but can be exposed by vias in case we decide we want to control the motor this way at some point. CLK is grounded. Step and Dir go to GPIO pins, preferably on the same GPIO port just because of how I wrote the software. VIO goes to +3V. GND pins go to ground. VS is +12V. A/B 1/2 are connected to the stepper motor. The order of the header coming from the stepper driver from left to right should be: A1, B1, A2, B2.

From bottom right going counterclockwise:

  • EN: connected to GPIO pin with an external pull up resistor to +3V
  • MS1/MS2: +3V
  • RX/TX: Floating, exposed on via
  • CLK: ground
  • STEP/DIR: GPIO pins, preferably on same port because of how I wrote software
  • GND: ground
  • VIO: 3V
  • B2-A2: Pin header. Order from left to right on header: A1, B1, A2, B2. Black wire will be on left side when connected servo.
  • GND: ground
  • VS: +12V, connected to ground with 100uf and 47uf caps

Next, I will start work on the homing sequence and slot alignment functions. I decided to add a field to the struct and check for it in the interrupt handler. The struct will be set to spin freely but with this “homing” flag enabled. In the interrupt handler, if the motor is spinning freely and this homing flag is enabled, it will check the status of the photointerrupter. If the photointerrupter is high, it will set position to 0, enable low and homing low.

Since I have been writing some code that utilizes this driver, I have realized I do not like the interface I have created. I have to use the stepper_await_position() each time after telling the stepper to move. For this reason, I decided to implement homing to await the homing to be finished by default. I will create an asynchronous and synchronous version of the homing function, and I think this should be the case for each function in the library.

I will use pin B0 for the photointerrupter. I also now have to allow the stepper library to read from this GPIO. I will add a field to the struct for the address of the IDR of the homing signal and the pin number that it is on. When I refactor the library, I will use the HAL and completely remove all register address passing from the interface. It makes the library too difficult to use, and the library will end up being hardware specific anyway. I am curious how peripherals are allocated in Arduino libraries, since you obviously do not need to specify which timer and GPIO ports you want to use.

After setting it up, I ran into an issue where the homing process would not happen at all. I realized this is because I forgot the photointerrupter is an active low output, so I need to wait until it is low, not high, to finish homing. After this, I encountered a problem where after homing, the rest of the program would only run about half of the time. This was very strange. At first, I thought maybe the behavior was different based on whether the step output was currently high or low when homing completed, but this was not the answer. I realized this because I took a small break talking to Brendan, and the motor randomly moved again. This meant the timer interrupt was not triggered for a long time. I realized that I must be setting the ARR to a value that is sometimes below the current CNT of the timer, so the timer has to overflow before it begins again. To solve this, I need to reset CNT whenever I start the motor. To do this, I need to add another field for the CNT register address. Once again, I need to refactor because this is annoying.

After making each function reset CNT before moving the motor, everything works as intended for the homing sequence. Now I will write the align_to_feed and align_to_dispense code. I am considering writing these as a wrapper module around the stepper motor driver, since the stepper motor driver is currently written pretty universally regarding usage, and could hypothetically be used for two different stepper motors (aside from the global declaration of step count problem). Having a wheel library could also make the main code look cleaner, since I could just call simple functions. I think I will do this. This design may or may not complicate the interface when using an RTOS.

example3

This is the header file I wrote. This interface will be very simple to use and only support 1 wheel.

Entry 3: -----------------------------------------------------------------

Date: February 27th

Start Time: 3:30 pm

Duration: 1 hour

In lab before class. I am continuing to troubleshoot the driver. Vref is still staying low. I tried using pull down resistors on TX and RX pins. I then tried putting the heatsink on the driver in case the driver was limiting current based on temperature. None of these attempts worked. I began searching for youtube videos. First I revisited the video where I discovered this driver: video, and looked at his wiring. In his setup, he grounded the clock signal and left the UART signals floating, so I copied this. This makes me confident that the issue is not UART related at all. I watched several videos on setting the Vref value, and eventually found this one that mentioned clipping the pins: video. I realized that one of the extra pins that I thought were just diagnostic outputs was actually also connected to Vref. The way the chip was inserted into the breadboard means it was shorted to the enable pin, which is grounded. This means my Vref was grounded, meaning my current output was at its minimum. I need to clip the pins as seen in the video.

After clipping the pins, vref is not 2 volts. I have to move the potentiometer to lower this limit. After lowering it to 600mV, the driver is now outputting around 200mV peak, and is not skipping when turning the wheel. However, I will raise the current limit to be close to the motor’s limit so that we can turn the wheel much faster. After class, I will verify the connections on the schematic for the motor driver, raise the current limit, write the align_to_feed_slot and align_to_dispense_slot functions, then continue my plan from entry 1. The new servo has also arrived, so I can test my servo functions on this.

Entry 2: -----------------------------------------------------------------

Date: February 26th

Start Time: 5:30 pm

Duration: 2 hours

Coming to lab to get new stepper motor driver working. This is the pinout of the new driver:

example3

I connected +3.3V to VDD, MS1, and MS2. This will give 16 microsteps, which is the most this driver provides. If this is not enough, we will revert to the drv8825. I connected RX (upper PDN on this diagram) to +3.3V with a 1K pull up resistor. I Connected VM and GND to 12V benchtop power supply with a 100uF and 47uF capacitor across the rails. I connected step and dir to the MCU outputs. Everything else is left unconnected. Plugging it in, the PSU hit it’s current limit and lowered the voltage. I realized the old motor driver was still connected to the power rails. I disconnected all connections from the power rails to this driver.

After attaching the motor, it would react to the steps from the microcontroller, but skip constantly. The current drawn from the power supply was also only 37mA. Now I will set the current limit of the driver. The reference voltage is currently 60mV. According to this website link, Vref = 1.47 * current limit, which seems to add up. I will need to increase the current limit by rotating the potentiometer counterclockwise.

I am noticing some strange behavior. When the stm is turned on first, the psu is drawing way more current once it is turned on compared to when the PSU is turned on first. This only happens occasionally.

I am having a problem where there is very little current being drawn by the stepper motor no matter how I orient the potentiometer, and it seems as though the current it lowering when the motor is moving, rather than raising. Vref is also not changing on the driver. I am wondering if the UART mode of the chip is enabled accidentally and if the UART mode is overriding any current limiting circuit. I removed the pull up resistor on RX, and for some reason this allowed the stepper motor to move more smoothly, but it is still drawing a similar amount of current, and is skipping a lot. Vref is still not changing.

I tried swapping to the other motor driver, but it behaves exactly the same. I tried running the motor at 20V, and it operates much better. It is still only drawing around 70mA. I am really hoping this is not a voltage issue, but a current one, since the motor is barely drawing any current. I am thinking it has to do somehow with the configuration of the driver, but I believe it is in the non-UART mode. I could use the UART mode, which would allow for software assertion of the current limit. I tried testing the Vref with the motor unplugged, but this did not do anything. Vref on the other motor driver is also not changing, and it is outputting just 6mV. This difference is probably just because I am measuring from a different ground. I may look into using the UART interface. When the motor is spinning well at 20V, it is very quiet, and feels premium. I just need to figure out why Vref is not being output at all. It is possible the chips have been burnt out, but I am not sure how this would be the case.

Entry 1: -----------------------------------------------------------------

Date: February 26th

Start Time: 9:30 am

Duration: 2 hours

I want to make sure everything that will be wired on the PCB will work. I need to test the new stepper motor driver with the new stepper motor, and soon I need to test the DC motor drivers and new servo. We also need to make sure we can get power from the power supply.

I decided to test the power supply first, since it is most critical. When plugged into a motherboard, the motherboard jumps two pins on the connector when the power button is pressed. I need to identify which pin this would be. According to this website, link, the ATX cable has a standardized pinout. This seems to align with our power supply, since pin 20 is not connected on our supply, which is standardized to be -5V. Our supply does not have a -5V output.

I am going to follow the instructions in this video linkto test the power supply and verify the pinout. First, I verified the PSU does not turn on normally. Then, I unplugged it and switched it off, then jumped pin 16 and 17 with some solder wire. I plugged the PSU back in and switched it on. This time, the fan started spinning up. This verifies the pinout of the PSU. We can use this to power the PCB.

example3

I then worked on getting the new stepper motor to work. The connection was slightly different:

example3

I verified that these were the connections of the coils by shorting each pair together and trying to move the motor. When either coil pair was shorted, the motor was very difficult to move. When other pairs were connected, it was easy to move. I also had to configure my code to use 200 steps per revolution instead of 400. The motor worked immediately with the same code. I then put the motor into the wheel, which has been printed, to see how it performs. The wheel was too heavy and the motor was skipping steps. The proportional control will definitely need to be appropriately tuned. However, there is too much tolerance in the wheel binding right now, and there is ~15 degrees of play in the wheel, even when the motor is not moving. This will need to be fixed mechanically. I tested how fast the motor can move without skipping. I ended up doing proportional control with a constant of .01, min speed of .5, and max speed of 2. This completed 180 degree movements smoothly, but I did not test any other values.

Johnny suggested I start working on the align_to_feed_slot and align_to_dispense_slot functions. My next steps are getting the new stepper motor driver working and then writing these functions, including a homing step. Then, I will write the DC motor driver code. Then, I will write the main firmware as a super loop, accepting UART commands and then acting on them. Finally, I will reimplement the main firmware with FreeRTOS. Once all of this is done, I will rework and tune the control of each kind of motor to ensure everything works as smoothly and quickly as possible. I cannot do this until all mechanical design is complete.

=============== Week 6: =================

Entry 6: -----------------------------------------------------------------

Date: February 20th

Start Time: 9 pm

Duration: 2.5 hours

I need to finish the software formalization. First, I wrote the testing plan to clarify what each part will be doing. Then I wrote the third party software section. Next I created diagrams in draw.io to outline the software components. I referenced the FreeRTOS website to clarify how the scheduler works and confirm how the tasks should be designed. I then created a descriptions for each component and how they would work together.

Entry 5: -----------------------------------------------------------------

Date: February 19th

Start Time: 3:30 am

Duration: 2.5 hours

In the lab before class. The DC motor arrived. Me and Johnny plugged it into the power supply to see how fast they were and how much current they would draw. Based on this datasheet the motor can handle 6-24V. At 6V, it was slow and drew around 190mA. At 12V, it was medium speed and drew around 280mA. At 24 volts, it was much faster and still drawing around 400mA. This means the l293d motor driver will be able to power the motor. However, we will need to combine the +12V and -12V outputs on the power supply if we want to power the motor at 24V. I am nervous doing this, since the -12V output can only supply .3A, which would not be nearly enough to power 2 motors. If this affects the quality of the +12V, it would affect the stepper motor as well, which could cause skipped steps. Krish says the amazon listing said 12 volts so we should not run it higher.

I will now work on the software formalization until class.

Next, I will create the servo motor and dc motor drivers.

After class. Going to get servo controller working. I will use PWM output of TIM3 channel 2 on PC7. This is the pins alternate function 2 according to the datasheet. According to this datasheet for the microservo I’m testing with, the pulses are between 900 and 2100 us. According to this datasheet https://www.mpja.com/download/31002md%20data.pdf, the period should be around 20ms. I will keep ARR as the max value and use PSC to get this period. 84000000 / 50 / 65536 (max arr) = 26. I will set PSC to 26 - 1 = 25.

I also realized the servo not only needs to be powered by 5 volts, but signaled at 5V as well. I will need to hook up a transistor. I will test and make sure 3.3V signal doesn’t work first.

example3

With CCR1 = 4000, the pulse is 1.2 ms, or 1200us. This should correspond to a position fairly centered on the servo. Plugging in the servo, it worked with a 3.3V signal and 5V power even though its rated for 5V signal. I will now write the servo driver. First I added “stepper_” to all stepper motor driver functions to avoid conflicts. I also renamed the library to stepper_control. In the future, I want to rework the stepper library to use degrees as inputs to functions. I will still need to store the position as an int to count steps and avoid rounding errors.

example3

I need to determine CCR values that correspond to 900 and 2100 us. 20ms is split up into 65536 slices. 900 / (20000 / 65536) = 2950. 2100 / (20000 / 65536) = 6881.

The library is very simple. I made a header file that defines the data type, which stores the address of the CCR register and the current position. The user initializes the timer in pwm mode with a ARR of 65535 and a period of 20ms, and passes in the CCR register. In the future, I should make these libraries use the HAL, since they will end up being hardware specific anyway. I could also have soft definitions in the library that the user has to define themselves, but this seems like asking too much of the interface.

example3 example3

I need to do more experimentation with the endpoints. Using these values, the full range of the servo is not reached. Seemingly does not match with the datasheet.

example3

Next I will find better endpoint values, then work on the DC motor drivers once the driver ICs come in. Then I will test wiring the new stepper motor drivers. Then I will get the RTOS working.

Entry 4: -----------------------------------------------------------------

Date: February 19th

Start Time: 9:30 am

Duration: 2 hours

Mandatory lab. In this section, I plan to research and order servo motors, work on the homing routine, and work on servo drivers.

I found this servo that should fit perfectly. It can be powered with 5V and is robust.

Johnny and Krish were discussing DC motor drivers, and I brought up one that I have used in a past project. It should be perfect for this project to drive two DC motors. It is an IC form factor, so it is much smaller than the ones we have been using. It is the L293D.

I will now work on the homing routine. First I need to connect the photointerrupter to the stm32. I decided to use port A0 since it is an unused GPIO port

I also wanted to work on the wiring of the new stepper motor driver. I went back to their ordering page to find information about the breakout board.

The wiring is very similar to the old motor driver, since it is made to be a drop-in replacement.

  • gpio on enable with a pull up resistor.
  • ms1, ms2, and VDD should be connected to +3.3v
  • additional 47uF cap between VMOT / VM and GND
  • bottom pdn and CLK should still be connected to +3.3v

I will test this wiring soon to ensure it is correct

Entry 3: -----------------------------------------------------------------

Date: February 18th

Start Time: 5:25 pm

Duration: 1 hour

Value High/Low Voltage
10K 50mV / 0V
47K 250mV / 10mV
100K 500mV / 60mV
500K 1.7V / .3V
817K 2.4V / .8V
1.4M 3V / 1V

It seems like the transistor acts as a current source, and larger resistors result in higher voltages. I believe the low voltage signals being above 0 is due to ambient light. I will choose the 1.4M resistor for the breakout board. I used the benchtop power supply to power the circuit so I could see the current draw, which was 5mA. If this ends up being too noisy, one way to improve signal would be to increase current draw through the diode to make a stronger light and use a smaller resistor at the output.

I finished the schematic for the breakout board:

example3

Next I will connect this to the micro and create the homing routing for the stepper.

Entry 2: -----------------------------------------------------------------

Date: February 15th

Start Time: 4:45 pm

Duration: 45 minutes

At the lab. I am going to work on getting the servo working rather than work on the photointerrupter, since I haven’t made any progress on why that isn’t working. I may use the arduino or AD2 to troubleshoot that in the future.

The servo we are using is a continuous rotation servo from botbrain.com This comes from the ME shop, so we did not order it and have the datasheet. botbrain.com no longer exists, and this servo is another servo that has a rebranding sticker on it as part of a diy kit. I also realized that continuous servos can only be input speed and direction, not position, so we will need a different kind of servo.

In the meantime, I will go back to try to make the photointerrupter work with the ad2. After using the multimeter, it seems that the diode is in the opposite direction than is listed on the datasheet. When wiring in this configuration, I get the expected 1V drop off through the diode, but the phototransistor is not opening. I will try reversing this side as well. This did not work.

Entry 1: -----------------------------------------------------------------

Date: February 15th

Start Time: 1:45 pm

Duration: 30 minutes

I need to make the software overview this week, so I need to plan the structure of the program. On the microcontroller, the main responsibilities of the software are stepper motor control, servo motor control, card feeder dc motor control, and UART communication. We need the motor control to not be interrupted, but still respond to the UART communication as quickly as possible. The two options for doing so are an RTOS, or prioritized interrupts. Prioritized interrupts are much simpler to implement, and are probably all that is necessary for this project. An RTOS could guarantee that motor control is not interrupted by UART communication, but would be more complex. It also is something I want to gain experience with. I believe the best solution is to mark the use of an RTOS as a stretch PSDR.

In either approach, the tasks should be prioritized this way: stepper motor control, DC motor control, servo control, then UART communication. The UART will store its data in a ring buffer in its interrupt, and be interpreted in the main loop. Motor control commands will be executed in the main loop. Stepper motor-based commands will be serviced several times by timer interrupts, while the servo and DC motors just need settings adjusted on their timer PWM outputs. Sending signals from UART will also be done in the main loop.

The pi will be responsible for receiving bluetooth signals from the app, receiving UART signals from the STM, performing computer vision card recognition using the camera, executing algorithms to optimize card order, and sending commands to the stm. This can also be done in a super loop, but should be interrupted by bluetooth signals in case the user sends a stop / reset command.

=============== Week 5: =================

Entry 5: -----------------------------------------------------------------

Date: February 13th

Start Time: 8:45 pm

Duration: 2.5 hours

Back at lab because I left my laptop charger, decided to get some work done while I am here. While thinking about the counterclockwise issue, I realized it was due to the same modulo problem I was having with the fastest_direction function regarding returning negative numbers. When position reaches negative 1, it should wrap back to STEPS_PER_REVOLUTION, but -1 % x = -1, not x - 1 like I had assumed when initially writing the code. I fixed this in the code, but I will not test until Brendan returns since he currently has UART code running on the STM that I don’t want to mess with. In the mean time, I will try to fix the reversal of clockwise and counterclockwise by swapping the define statements. This didn’t work before, but this is probably also due to the negative rollover problem.

Now I will try to implement proportional control for smooth ramping up / down of speed. Once proportional control, alignment to a particular card slot, and homing sequence are all functional, I will move onto the servo motor driver. After this is done, I will write create a program that will allow for the control of the stepper and servo using the pi console interface. This program will allow for setting the servo and stepper to particular positions and adjusting speeds of both for calibration with the mechanical design. Commands will be sent over uart to the stm, which will be interpreted into wheel movement.

For now, the minimum and maximum speed should be set to the most extreme value that the stepper motor can run at without skipping steps. In the final design, this can be determined using the pi calibration application. The magnitude of the proportional constant will affect how dramatic the ramp up is between these two values.

I have also decided to have the struct store the speed as rotation per second, and just interpret it into ARR values when setting the speed. This will make the struct data much nicer to read when debugging. I also added a speed field to the struct that won’t have any practical purpose but is good to know for debugging. I want to change p to not change based on steps per revolution, so I created a position to degrees function to normalize this. This is the current state of the proportional part of the interrupt handler:

example3

I then added an init_pos field that is stored whenever proportional control starts. This allows for ramping up in speed as well as ramping down:

example3

Everything works as it should, but some tuning will be required once we have the actual motor and wheel to maximize speed and stability. I will wait until we have the actual wheel to write the slot alignment functions. Now I will work on the homing sequence. First I need to wire up the optical sensor. This is the circuit from the datasheet:

example3

I need to bias the phototransistor so that the led will engage it. The transistor is rated for a maximum current of 20mA, and they tested with Vcc = 5V, Rl = 100 ohms, IL = 5mA. I will also use a 100 ohm resistor. The diode is rated for 50mA, and they use a 220 ohm resistor with five volts. The forward voltage is 1.2-1.5V. 3.3-1.5 / 220 = 8mA, which should be enough. If the switch doesn’t work, I will first try lowering this resistance.

This did not work. When I wired the LED backwards, current would come out of the power supply, and the voltage did change on the output when the sensor was blocked compared to not blocked. However, the voltage change was .6mV. This is clearly not the intended setup. I will research this more and come back prepared to fix.

Entry 4: -----------------------------------------------------------------

Date: February 13th

Start Time: 3:25 pm

Duration: 2.5 hours

In lab before class working on motor control code. Going to see if changes made cause timer interrupt to be called.

Running the code, the speed_to_arr function now works properly. Also, the timer interrupt is being triggered. However, the breakpoint on the ISR is being called while that ARR of the timer should be 0. This could cause problems if the ISR is called before the motor is initialized. To fix this, I just moved the start_timer HAL function after the stepper initialization. There is probably a better way to design this, but this is how it will function for now.

Now that I know the ISR is being called, I can write it so that it outputs steps appropriately. First I will write code so that spin_freely works, then goto_position and await_position, then goto_position_proportional. Goto_position/await_position will require extra checking/manipulation of position-related flags, and goto_position_proportional will require extra math and adjustments to the timers ARR register.

For spin_freely, there is no need for position tracking yet. I just need to check if the motor is enabled, and toggle step if it is. I am also remembering that the timer ISR needs to happen twice for each step of the motor. For this, I will adjust my speed_to_arr function to cut the return value in half. Also, the address of the stepper object is not currently available to the interrupt handler. To fix this, I will make a_stepper a volatile global variable in main.c, and pass it to the handler. This is the current state of the interrupt_handler that can handle spin_freely:

example3

I hooked up the AD2 to read the step pin, then called spin_freely with a speed of 2rps and ran the program. This was the output:

example3

The frequency is 25.521kHz. Freq / steps_per_revolution / microstep = 25.521kHz / 400 / 32 = 1.99. This looks like everything is working. I tried again with 3 steps per second:

example3

And .5 steps per second:

example3

Spin freely works as intended. I also tested the program only calling set_speed and not spin_freely to ensure there would be no output, and there was not.

I then made sure the direction was being set properly by spinning freely in the clockwise and counterclockwise directions. I decided to add a function to stop the motor so I could send it one way, delay, then send the other way. The new function is stop_spin(). I may need to change the names of these functions so they do not conflict with the other motor libraries I need to make, since similar names will be needed for the card feeder motors. Based off of this alternating function, the step and dir signals seem to be behaving properly:

example3

I decided to attach the signals to the motor driver to see if everything worked properly. It did. The motor would move clockwise for a second, stop for a second, then move counterclockwise for a second. Each time seemed to move half a rotation, which is what the speed says it should.

Next, I will update the interrupt handler to target certain position. Class is now starting.

After class. I added code to track position and check if it equals the target position. One thing to note is this approach will leave the step input high once the target is reached, but the driver only considers rising edges on step, so this is okay:

example3

This is the completed goto_position function:

example3

I need to write set_optimized_dir() to determine which direction would be faster. To do this, I will find how far the position is going clockwise. If it is more than half a rotation, then counterclockwise is faster:

example3

I had to add + STEPS_PER_REVOLUTION within the mawth to deal with negative values, which would return negative numbers after the modulo. This is the final await_position function:

example3

To test this, I will target one position with the ad2 connected and ensure pulses begin, then end. I will then check the stm debugger to see the position of the motor. If it lines up, I will attach it to the motor and ensure everything looks proper. The debugger looks proper:

example3

For simplicity, I added a function to convert degrees to position in terms of steps. I then set up a test to move to 270 degrees, then 40 degrees, then 0 degrees. This worked, but only in the clockwise direction. I need to do more testing to figure out why counterclockwise doesn’t work. Also, I realized that my clockwise and counterclockwise are reversed in code. Next steps is to fix this reversal.

Entry 3: -----------------------------------------------------------------

Date: February 13th

Start Time: 3:25 pm

Duration: 45 minutes

I want to see if my setup for the motor control is working. First, I filled out the spin_freely() function so that it would actually change register values and hypothetically work:

example3

I debugged the program to see if the timer ISR was being called by setting a breakpoint on the interrupt handler. It was not. Stepping through the program, It seems like my helper function for converting a speed to an ARR value is always returning 0. The timer ARR is then set to 0, which means the counter is disabled. In addition, I realized that the base configuration of the timer does not set the counter enable bit, so the counter is disabled that way as well. To enable the timer using the HAL, the HAL_Tim_Base_Start_IT() function is used. I also set the default configuration of ARR to be 0 instead of max.

I tried adding a (float) typecast to the speed to ARR function, but this did not work. I realized that the values of steps_per_revolution, clock_speed, and period were not being set properly. I am using global static variables to store these values. To support multiple motors, these should probably be included in the stepper struct anyway. However, I realized the reason they weren’t being set is because I had parameters in my init function with the same name, so writing microstep = microstep was ambiguous. I fixed this issue, but I did not have time to test it.

Next steps are to test if this fixed my timer isr not being called, then to write the actual interrupt handler so that steps are output properly. After this is done, I can complete all other movement functions, then move onto homing sequence. I will work on this after class tomorrow.

Entry 2: -----------------------------------------------------------------

Date: February 13th

Start Time: 3:25 pm

Duration: 45 minutes

While the tas are visiting each team, I cannot checkout a new stm. I will be using my own stm32f446RE that I brought to start the motor control code. Since we will eventually be switching to an F7, we need to write the motor control fully abstracted from the hardware. The frequency control of the pins will act differently. This is the pinout of the f446re from the user manual downloaded from

st.com example3

I will be using PC0 as step output and PC1 as dir output. I started setting up the timer in the stm32 cube ide. I am not a big fan of using the ioc file for configuration, since it isn’t very clear on the effect everything as on which registers. I will try it for now. The slowest we would reasonably want the step to output, as discovered yesterday, was 6.4khz. The way I am implementing motor control means the timer needs to overflow at 12.8khz. The input to the timer is 84MHz. At 32bit ARR value and no prescaler, the slowest it can go is 84Mhz / 2^32 = .02Hz. This is definitely slow enough, so we don’t need to adjust the prescaler.

I set the clock source to internal clock and enabled the TIM2 interrupt. I also enabled the HSE in the RCC section. I generated the code for this configuration. I went into the interrupt handlers file and found TIM2_Handler. It calls a HAL function called HAL_Tim_IRQ_Handler(). I followed this function, and saw that it calls a function called HAL_TIM_PeriodElapsedCallback() when an update happens. This function is not defined by the HAL. I defined this function in my main.c. I also created a header and source file called motor_control.h/c. In this library, I declared a function called motor_timer_interrupt_handler(). This is where the interrupt activities will happen. This function will need to be called by whatever hardware-specific interrupt occurs on timer update. I also declared a struct type for the stepper and all functions based on my plans from before:

example3

I decided to change the interface to have the caller supply the address of the stepper. This will allow static allocation of structs, which is better for embedded systems:

example3

I wrote the init function, which just basically assigns each value of the struct. I then wrote the set speed functions. Each one needs to convert a speed float in revolutions per second into a timer ARR value. I need to work out the math for this:

ticks_per_second = (clock_speed / (prescaler + 1))

ticks_per_second / (ARR + 1) = steps per second

steps per second / steps_per_revolution = speed

This is the final formula:

arr = (clock_speed / (prescaler + 1)) / (speed * steps_per_revolution) - 1

I used this in the min, max, and set speed functions. I wrote the spin_freely, goto_position, and goto_position_proportional, and await_position functions. These each need to disable the motor, ensure the target_pos_flag, target_pos, proportional, and p fields all make sense, and make sure the dir output is correct, then enable the motor. To do so, I added a dir parameter to spin_freely, goto_position, and goto_position_proportional. This is the final interface:

example3

Next, I need to write the interrupt handler and test the hardware without the motor. First I will make sure the timer interrupt is being called. By simply flipping a GPIO pin every time it is called. Once this is working, I will use the actual interrupt handler. Once it looks like it works, I will test it with the actual motor. Then I will need to make the homing sequence.

Entry 1: -----------------------------------------------------------------

Date: February 13th

Start Time: 3:25 pm

Duration: 45 minutes

Going to lab after class to replace the stm and motor driver and try again to get the motor moving. The new stm board is a stm32f411re nucleo board. The replacement driver is another drv8825 board. I want to test the stepper motor without the driver to ensure that it is not the problem. I shorted each combination of two wires together and tested if the motor was easy to turn. Only the black and green combination and red and blue combination affected the motor. This means there is a good chance the motor is functional.

I then wired the stepper motor driver as before. This time, I am just using the direct output of the buttons as the step and motor signals, rather than filtering them through the stm. I connected the driver to the bench power supply this time, with an output current limit of 1A. I then disconnected the motor from the driver before adjusting the current limit. I wasn’t sure what the limit should be, since I am using an unlabeled stepper motor from the cabinet, so I set the reference voltage to .3V. This would give the driver a motor output current limit of .6A.

I then plugged in the new stm board, and got an error message. The board was again fried (this time not by me, but the previous user). As a replacement, I used the AD2 that was at our station to power the logic side of the circuit. After connecting the AD2 power supply to the logic side voltage rail, I powered it on and tested the button circuitry, which seemed to work. I then turned on the output of the bench power supply. When pressing the button connected to the step button, I didn’t see any movement on the stepper motor. The benchtop power supply was outputting around .2A, and the stepper motor was unable to be moved by hand, so things seemed to be working otherwise. To troubleshoot this, I adjusted the current limit again so that the reference voltage was .5V. The output current limit would now be 1A. After powering everything on again, I held the motor while pressing the step button, and felt the motor move with each press. At long last, the motor finally works. I was hoping to get started on the motor control driver code, but the stm board being broken means I cannot yet. Tomorrow during lab, I should be able to make strong headway in this area, especially considering I have pseudocode for everything.

To see the servo motor rotate, I connected a digital logic pin from the AD2 to the step input. I then set a pattern output to output step at 10Hz. When turning it on, I realized that the motor isn’t moving, just vibrating on every step. To fix this, I ran the driver at a higher voltage. This solved the problem. I then started experimenting with different speeds and voltages. There was some skippage around 200Hz at 18V, but everything worked fine around 500Hz-2KHz. It wasn’t able to support 2.3KHz. The same was true at 12V. The motor could immediately jump to 500Hz with no issues, but around 200Hz would have skipping problems. This seems like it may be solved by a different microstepping mode. I set the motor to run for 200 steps using the pattern generator in waveforms:

example3

This resulted in half a turn, making it seem like this motor is either a 400 step motor, or the driver is in half step mode. Since pins m0-m2 are pulled low, which should be full step mode on the drv8825, it is most likely a 400 step motor.

example3

Note: when powering on / off the motor, I am first disabling the AD2 (micro) power, then turning off the motor driver. I do this in reverse order when powering it on. This order does not seem to matter however.

I set pins m0-m2 to high to engage 1/32 step mode. When running the motor at 12.8khz for one second, it completes one rotation (400 * 32 = 12800). Cutting this in half (6.4khz) for the equivalent of what was 200 hz before, there is no skipping issue at all. It seems to also top out around 5rps though (300rpm). We will use a microstepping setting for the final design that ensures our micro is able to output fast enough pwm for 5rps.

The final state of the bench power supply limits was 12V, .5A. While active, the motor drew around 120-250mA.

Next, I need to order a servo motor for dispensing, or determine that the servos I have at home are sufficient. After this, I will check out a new stm board (for the fourth time), then I will finish the servo motor control code, then work on the homing sequence using the optical switches, which arrived in the mail. At some point, we also need to figure out how to jump the pc power supply so we can use it.

=============== Week 4: =================

Entry 6: -----------------------------------------------------------------

Date: February 6th

Start Time: 5:20 pm

Duration: 1.5 hours

Meeting after class in lab. I tried more combinations of ammeter, measuring each coil as well as coming from the power supply. In each, very minimal current was flowing through the chip. The motor driver chip was also getting very hot despite not drawing much current.

I connected the nEnable pin to to ground and it had no effect.

I drove each pin to the logic level that it should be at, despite internal pull up/down resistors that should be present. Each pin is now connected exactly to what it should be, but it is not working.

I tried more to adjust the current level to 1.8A, this time using the reference voltage. The current limit is 2 * reference voltage. The reference voltage read at 1.1V, and was not moving even after adjusting the potentiometer.

After unplugging the power supply, I adjusted the potentiometer and plugged it back in. The voltage level still did not change. I decided to adjust the current limit while it was plugged in, which is what all videos demonstrating this feature have done. Unfortunately, as I was doing this, the screwdriver slipped and shorted pins on the driver. It immediately smoked up. This also caused a power surge to the stm32 that was powering the logic side of the driver. Unfortunately, the stm32 was being powered by Brendan’s laptop. The power surge caused Brendan’s laptop to turn off. We opened up the laptop and nothing was burnt, but the laptop would no longer turn on. The battery could still supply power to the raspberry pi. Luckily, Brendan was using a backup laptop. This is a very tragic event :(

Next steps are to check out a new stm32, and await the new motor and motor driver. This way we will know all parts are functional. I will also not test until we have a 12V power supply because it will be safer. In the future, when power supply power is involved, we will use a wall plug to power the stm32 to protect laptops. Also, I will not adjust the current limit while it is plugged in. I will blindly move the potentiometer, then re-plug it in. Also, I will fully rewire the stepper motor driver circuit before testing in case there were issues before.

Entry 5: -----------------------------------------------------------------

Date: February 6th

Start Time: 3:25 pm

Duration: 1 hours

Came to lab before lecture. Grabbed a 15V, 2.2A power supply. Double checking wiring, then going to power the power supply.

I want to use the multimeter to measure current through the motor driver. There is an input that has a fused 12A maximum. The smaller ammeter setting is fused at 1.25A.

I ended up switching to a 24V, 6.3A power supply because there was no 120V AC cable attached to the 15V power supply. I plugged the power supply into a power rail on the breadboard and used the multimeter to measure the voltage, and it measured 24V. The voltage slowly ramped down to 0 after being unplugged.

Before operating the motor, the current limit on the driver needs to be set. I went back to this website about the motor driver breakout board: https://www.pololu.com/product/2133 and found this section about setting the motor current limit

example3

I set up the multimeter to measure current through one coil, and connected power supply leads to the driver. After it’s on, I will record the measured current. Since we want the current limit to be “at or below” the motor current rating, we will set the limit at 1.8A. .7 * 1.8 = 1.26. We want to adjust the potentiometer on the driver until the idle current is at about this level.

After plugging in the power supply, nothing happened. I then plugged in the microcontroller to supply logic voltage supply. Plugging the power supply in after this resulted in a burning electronics smell, probably meaning I burned the motor driver, but possibly not. The stepper motor has no torque when the power supply is plugged in. After adjusting the setup to measure current coming from the power supply and plugging it back in, the multimeter reads about .1A. Next thing I will test is pulling the nEnable pin low or high in case the pins are not driven low on this knock off driver.

After some research, it is possible that there was a problem with my wiring using the ammeter to connect the stepper motor driver to the motor. If this connection isn’t correct, the driver will be fried instantly.

Entry 4: -----------------------------------------------------------------

Date: February 5th

Start Time: 10:00 pm

Duration: 1 hour

Planning stepper motor control software. According to TMC2209 datasheet, https://www.analog.com/media/en/technical-documentation/data-sheets/TMC2209_datasheet_rev1.09.pdf, steps occur on the rising edge. To control steps, a timer will be used on the stm32 in upcounting mode. On every update, an interrupt will be triggered that will toggle the step output. If it is a rising edge, the position of the motor will be updated to be changed by one step. The speed of the motor can be controlled by the TIMx_ARR register. A higher value will mean less frequent toggles and slower speed. This operation will allow other tasks to occur on the microcontroller and be interrupted by the motor control ISR. To control the motor, simply set the speed, then enable it.

To allow stepping to an exact angle, enabling the motor can be accompanied by a desired final position. The ISR will check whether it has reached this position each time the position is updated. If it has, it will disable the motor. This could also be accompanied by an optional speed ramping flag. We could use proportional speed control depending on how close the motor is to its target position. The ARR value will be adjusted by the timer ISR. There should be a cap on this speed.

Given this method of control, motor parameters should be stored in a struct with these fields:

bool step; (step output)

bool dir; (dir output)

int position; (stored in steps, rolls over at 1 rotation worth of step counts)

int min_arr; (max speed represented as minimum TIMx_ARR value.)

int max_arr; (min speed represented as maximum TIMx_ARR value.)

bool target_pos_flag; (if targeting a position, set true)

int target_pos; (target position)

bool enable;

bool proportional;

int p; (proportional coefficient)


Interface:

set_max_speed(int speed);

set_min_speed(int speed);

set_speed(int speed);

spin_freely();

goto_position(int position); (sets target_pos, target_pos_flag, and enable)

goto_position_proportional(int p); (sets proportional and p and calls goto_position)

await_position(); (wfis until enable && target_pos_flag is false)

ISR psueocode:

// clear flag

// if (!enable)

// return

// step = !step

// if (step)

// increment/decrement position depending on dir

//

// if (target_pos_flag and position == target_pos)

// enable = false

// return

//

// if (proportional)

// TIMx_ARR = (position - target_pos) * (1 / p)

// adjust based on min and max ARR values

//

// adjust step and dir outputs to reflect variable values

Entry 3: -----------------------------------------------------------------

Date: February 5th

Start Time: 2:45 pm

Duration: 5 minutes

Sitting down to update the PSDRs based on feedback in lab. In lab, they mentioned to emphasize that the microcontroller is responsible for the functionality mentioned, and to remove requirements that are too specific. These are the new PSDRs:

    • PSDR #1 (Hardware): An ability for the microcontroller to interface with a stepper motor driver to move stepper motor in precise increment.
      PSDR #2 (Hardware): An ability for the microcontroller to communicate with Raspberry Pi over a UART connection.
      PSDR #3 (Hardware): An ability for the microcontroller to control brushed DC motors with certain speed and direction to manipulate cards.
      PSDR #4 (Software): A mobile application that can be used to select desired order of cards and communicate with raspberry pi via Bluetooth
      PSDR #5 (Software): An algorithm that determines an order of loading/unloading cards optimized for speed given the original order of deck and parameters concerning shuffled order of cards
  • Entry 2: -----------------------------------------------------------------

    Date: February 5th

    Start Time: 9:30 am

    Duration: 2 hours

    Mandatory lab. Goal today is to order a stepper motor, motor driver, and motor for prototyping.

    We discussed the power supply issue with the TAs and professor and determined the PC power supply would be the easiest way to power it. They also have single output DC power supplies we could check out. I submitted the part checkout form for a 12V DC power supply.

    I reviewed old journal entries to determine this is the motor driver and motor we want: https://biqu.equipment/products/bigtreetech-tmc2209-stepper-motor-driver-for-3d-printer-board-vs-tmc2208 https://www.omc-stepperonline.com/e-series-nema-17-bipolar-55ncm-77-88oz-in-2a-42x48mm-4-wires-w-1m-cable-connector-17he19-2004s?srsltid=AfmBOoqQ0aRzwvS95f9eypuwsZrFMQn-GvnqzHLacF40XWM9_4hp-BEN

    I also consider the homing mechanism. This website recommends a photointerruptor and something on the wheel to go between it: https://ponoor.com/en/docs/step-series/functional-description/homing-and-position-management/

    I looked for photointerruptors on digikey and found this one with an 8mm sensing distance: https://www.digikey.com/en/products/detail/omron-electronics-inc-emc-div/EE-SX1070/252461

    Entry 1: -----------------------------------------------------------------

    Date: February 4th

    Start Time: 3:30 pm

    Duration: 1 hour

    Before class, I went to the lab and researched power supply options for the stepper motor. When I arrived, there was a package containing the 12 decks of cards that we ordered.

    Our current plan is to purchase a PC power supply. This would be very simply for prototyping and have many separate terminals we could use. Another option is a dedicated power supply for the motor. This website describes several options: https://teknic.com/selecting-power-supply/

    I know 3d printers are a common use case for stepper motors, so I looked up what hobbyist 3d printers use. This website recommends a mean well 24 or 12 V power supply: https://www.drdflo.com/pages/Guides/How-to-Build-a-3D-Printer/Power-Supply.html#:~:text=It%20requires%20a%20low%20DC,a%20row%20of%20screw%20terminals.

    The 12V is probably more appropriate for our use case: https://www.amazon.com/MEAN-WELL-LRS-350-12-Single-Switchable/dp/B0109IMRPS/ref=as_li_ss_tl?crid=29U3R4805QCBM&keywords=meanwell+power+supply&qid=1574134912&sprefix=meanwell+power+supply,aps,140&sr=8-1&linkCode=sl1&tag=drd0cf-20&linkId=b3918846d35f24e6d7cfade4ac7f96b0&language=en_US

    12V and 29A output should be more than enough to power our entire project.

    Johnny arrived and discussed using a PC power supply. They seem to be very cheap and applicable to the purpose: https://www.amazon.com/Apevia-SPIRIT600W-Auto-Thermally-Controlled-Protections/dp/B0B9VGG83Z/ref=sr_1_37?crid=KFJO9X7AZLC4&dib=eyJ2IjoiMSJ9.72daOWBE-JQsM_-4BVPYtSqML2SgZgOQ5W9T5siUdU6DCA1FC4LyLqTZzYoFcxVEPkzVDRQWMkJzFMVtXTN-MwQSgC8r4LnasECSVygB8mek5RPPEIjlmCpYw9fpTEmwuA5kwY2X3Jmy0rv5mYzggZL94e1RIGfjBHm4U_IIlPFSzCOline-4yHhFvAovKV4w5wyrWgT8r4IidAgpz_M01ATIMfNodHULahj01y4Q4k.X3IaTKax7qBFCkbnNroSdGCve_Li1QM__urvys__5f4&dib_tag=se&keywords=pc+power+supply&qid=1738721457&sprefix=pc+power+suppl%2Caps%2C124&sr=8-37&xpid=J9_jjpNO7H1LH

    In this listing, it does mention that the power supply will only turn on if the power cable is properly connected to the PC. There may be a problem with trying to get the power supply to turn on if it is somehow expecting a PC. It may be a more surefire option to get a normal DC power supply.

    Next steps are to discuss power supply with the group in lab tomorrow and submit an order for whichever we decide on. We also will be deciding on and ordering motors / motor drivers.

    =============== Week 3: =================

    Entry 5: -----------------------------------------------------------------

    Date: January 30th

    Start Time: 5:30 pm

    Duration: 3 hours

    We met after class to work on the project. My goal is to get the stepper motor test working.

    First I wired buttons up, connecting one side to VCC from the STM32 Nucleo, and one side pulled to the STM32 ground with 10k ohm resistors. I connected the side pulled to ground to ports labeled A0 and A3 on the STM32. I then connected output wires from the Nucleo board to the breadboard that will be used for step and direction. I hooked up a multimeter to ensure my program would work. After configuring port A using the Cube IDE and writing the program, it did not work as expected. I looked up the pinout for the board and realized that A0-A5 did not actually correspond to Port A pins 0-5: User Manual

    example3

    After adjusting the wiring and configuration to PD7 - PD4, I rewrote the code. I was having issues using the STM32 HAL since I have never used it before. Using the CMSIS framework, I was able to get the code to work as expected:

    example3

    I realized my issue was I needed to use the macro GPIO_PIN_5 instead of the number 5, and the code now works.

    example3

    This is what the button wiring looks like:

    example3

    I then wired up the stepper motor driver according to the diagram in entry 4.

    example3 example3

    With this setup, the top button is step and the bottom button is dir. I attached the power supply to run the motor, but I realized the current limit at 8.1 volts is only 1 amp, when our stepper motor runs at 2A per coil. Next step is to find out what we can use to power this motor. I will also consider more robust wiring before turning it on.

    I also successfully SSHed into the Raspberry Pi after Brenden set that environment up. Finally, I updated the PSDRs on the website:

    • Hardware: An ability to interface with a stepper motor driver to move stepper motor in precise increments equal to or less than 1.8 degrees
    • Hardware: An ability to communicate with Raspberry Pi over a UART connection.
    • Hardware: An ability to control brushed DC motors with certain speed and direction to manipulate cards
    • Software: A mobile application that can be used to select desired order of cards and communicate with Raspberry Pi via Bluetooth
    • Software: An algorithm that determines an order of loading/unloading cards optimized for speed given the original order of deck and parameters concerning shuffled order of cards

    Entry 4: -----------------------------------------------------------------

    Date: January 30th

    Start Time: 3:25 pm

    Duration: 1 hour

    Before Thursday class section. Went to lab and checked out a stepper motor driver IC. It appears to be identical to this one: Pololu DRV8825. It is a breakout board for this: DRV8825. The Pololu website has tips on how to use the driver.

    example3

    The website also recommends a >=47uF capacitor between VMOT and ground. Pulling M0, M1, and M2 to combinations of low and high results in different step resolution. At first, I will keep them disconnected, as they are pulled low by default for full step mode. Reset, sleep, and enable are all pulled low by default, so nreset and nsleep need to be pulled high.

    There is a potentiometer on the ic that needs to be adjusted for proper current limiting. If it is not set, the stepper motor will skip steps. The website has a video that explains how to set this: https://www.youtube.com/watch?v=89BHS9hfSUk

    It is not recommended to use this IC without cooling above 1.5A per coil. The stepper motor I got from the cabinet is rated for 2A per coil. In the final design, a heatsink may be required on the driver.

    Next, I will create a simple program on the stm32 that will toggle DIR when a button is pressed and pulse step when a button is pressed. Then I will wire the stepper motor according to the diagram and use the micro to test it. Once this is set up, I will set the stepper motor driver to use different sized steps to determine which will be optimal for our design. Then, I can get started writing fully-fledged motor driver code, since our motor drivers use this step/dir interface.

    Entry 3: -----------------------------------------------------------------

    Date: January 29th

    Start Time: 9:30 am

    Duration: 2 hours

    Mandatory lab. I mentioned to the group that a standard nema 17 stepper motor will be sufficient to control our wheel. I grabbed a stepper online motor from the used parts closet. We still need to get a stepper motor driver. We met with tas and discussed our functional description and PSDRs. Both need to be updated on the website.

    We split into two groups: me and Brandan focus on getting the stm32 up and running, and Krish and Johnny work on the design of the card dispenser.

    Brendan installed the stm32cubeide on his computer. I already have it installed. After setting up a project using the nucle-f746g board, I attempted to set a bit in the GPIOB ODR to turn on the green led that is on the development board. When trying to upload, I encountered an error:

    example3

    Looking more closely at the board, I noticed one of the LEDs that turns on on the boot loader side is “over current”, meaning something is being shorted on the board that shouldn’t be. We need to get a different board.

    We checked out a nucleo f4 because there were no f7s available. Plugging the new one in works. Brenden was able to upload code to it. Next steps are to get a stepper motor driver and begin prototyping.

    Entry 2: -----------------------------------------------------------------

    Date: January 28th

    Start Time: 10:00 pm

    Duration: 30 minutes

    Since I will begin writing motor control code soon, we need to think about the structure of the software on the STM32.

    Duties:

    • Communicate with raspberry pi
    • Get given parameters for shuffle
    • Receive computer vision results for each card
    • Control wheel
    • Control offloading mechanism
    • Control dispensing mechanism

    Requirements:

    • Easily modifiable behavior
    • Possible that we decide to input cards in the shuffled order - wheel control will need to happen differently in this case. Minimal change to main program should be needed for this to happen
    • Abstraction from device drivers
    • Communication with raspberry pi does not interfere with mechanical processes

    How this affects wheel control:

    • Interface should be simple
    • homeMotor()
    • setMotorAngle(angle)
    • Even simpler?
    • alignDispenserToSlot(slot #)
    • alignOffloaderToSlot(slot #)

    Need to consider how to change physical design to allow for homing motor. (limit switch? Optical switch? Move limit switch out of way with cheap servo?)

    Next is to discuss homing method with team and start writing motor controller drivers once we have the motor and driver IC.

    Entry 1: -----------------------------------------------------------------

    Date: January 28th

    Start Time: 5:30 pm

    Duration: 1.5 hours

    After class, researching stepper motors for wheel.

    It seems a servo motor with an absolute encoder could be the simplest to work with for our design. There are some tradeoffs:

    Pros Cons
    Servo Less power draw, more accurate, faster Much more expensive, more complicated drivers
    Stepper Cheaper, simpler Slower, less torque

    Most kinds of divers for both motors use similar control scheme: direction and step signals. However, the cost tradeoff for the servo is extreme, and the precision and torque of stepper motors seems to be more than enough for our application. Stepper motors are used in 3d printers and cnc machines, so they are definitely capable of this task.

    Stepper motor description / how to use: https://www.youtube.com/watch?v=bkqoKWP4Oy4 Going to want motor driver ic (designing basic motor driver would be simple enough, but high-precision would require much more design)

    Stepper motor speed test: http://youtube.com/watch?v=sZNrYDkJLgY NEMA 17 stepper motor - fairly standardized Could jump straight to 200rpm with no problem Might be more difficult under load

    Different NEMA 17 stepper motor comparison: https://www.youtube.com/watch?v=MNTuMiNC2TU

    Good stepper motor driver IC: TMC2209 Died at 24V in video https://bttwiki.com/TMC2209.html#pinoutfunction - prototype board https://www.digikey.com/en/products/detail/analog-devices-inc-maxim-integrated/TMC2209-LA-T/10232491 - IC for pcb

    Good stepper motor - https://www.aliexpress.us/item/3256804544882764.html?aff_fcid=3ea110aa62e74df6904c24b78fe101b0-1738130343837-02719-_DCFVJhl&tt=CPS_NORMAL&aff_fsk=_DCFVJhl&aff_platform=shareComponent-detail&sk=_DCFVJhl&aff_trace_key=3ea110aa62e74df6904c24b78fe101b0-1738130343837-02719-_DCFVJhl&terminal_id=0b85f63cb5df44c1a6ce4c07ce1caf36&afSmartRedirect=y&gatewayAdapt=glo2usa4itemAdapt

    Next steps are to order the stepper motor and prototyping IC (or see if the lab already has both of these / equivalents) and set up tests using the STM32 prototyping board. Once we confirm the motor does what we need it to do, we will design the CAD models with this motor in mind and begin working on motor control interface.

    =============== Week 2: =================

    Entry 5: -----------------------------------------------------------------

    Date: January 24th
    Start Time: 1:30pm
    Duration: 1 hour

    Me, Brendan, and Johnny met at the lab so we could talk to the machinist about which design he thinks would be less likely to cause mechanical problems. He recommended the wheel. He also mentioned that if we were going to use his machine shop, we should use autocad and imperial units.

    Once we decided on the wheel, we spent some more time discussing and finalizing our design. The wheel will be surrounded by acryllic to prevent cards from falling out while spinning. Two slots will be cut in the acryllic: one by the feeder, and one by the exit. The exit will also have a servo or solenoid attached to a trapdoor to allow cards to escape. We debated how thick the slots for each card should be, since each card is extremely thin, but we want to be able to consistently shoot it into the slot. We ball parked around 5mm. The plan is to feed cards into each slot, then dispense them in an optimized order, or fill the cards into the slots in order, open the trapdoor, and quickly dispense the cards in succession. This decision will be made farther down the line, since it doesn't affect mechanical design.

    Entry 4: -----------------------------------------------------------------

    Date: January 23rd
    Start Time: 5:30pm
    Duration: 2 hours

    After class, we met in the lab to plan out who would be responsible for which roles so that we could do more independent work going forward. My assigned roles are wheel motor control, card dispensing control, and co-lead for shuffling algorithm. During independent time, I need to research different motors we could use for the wheel to maximize speed and precision while minimizing torque.
    example3

    Entry 3: -----------------------------------------------------------------

    Date: January 22nd
    Start Time: 9:30am
    Duration: 2 hours

    In manlab, we debated which design we should go with: the one from the completed video, or the wheel design that the other group attempted. We also decided we would use a raspberry pi to interface with the camera, do computer vision, and host the web server for the app. We decided on an STM32F7 microcontroller, since we used the F line before in 362, and the F7 is a high end micro for prototyping. We were going to meet with the machinist to discuss which design he would recommend, but he was not present.

    example3

    Entry 2: -----------------------------------------------------------------

    Date: January 21st
    Start Time: 5:30pm
    Duration: 15 minutes

    After class Tuesday, we met and discussed our goals for the week. We decided that we wanted to decide on our design and order all prototyping parts so we can begin working. In lab tomorrow, we will get some prototyping boards and decide on a design

    Entry 1: -----------------------------------------------------------------

    Date: January 20th
    Start Time: 5:00pm
    Duration: 15 minutes

    Johnny and Krish sent a video of a design that does exactly what we are planning to do. It uses a moving stack of slots. This is a good resource, as it is a design that we know works that we can take inspiration from. https://www.youtube.com/watch?v=eMTXyl7tPEk After seeing this, I tried to see if there was any other similar designs that use a different structure, and found this example of a wheel: https://www.youtube.com/watch?v=EKzgN_-8iP4 These references will help us as we begin planning our final design.

    =============== Week 1: =================

    Entry 3: -----------------------------------------------------------------

    Date: January 17th
    Start Time: 2:30pm
    Duration: 1.5 hours

    I did some brainstorming alone in my dorm to see how we could manipulate cards. I found some videos about playing card sorters that have similar mechanisms to what we would need. The most useful seems to be the adjustable feeder foot design for feeding one card at a time. Some high end sorting machines used suction cups to grab one card at a time, but this is way to slow for our needs. The conveyors moving cards to bins is nice, but doesn’t fit our needs, since we need to reconsolidate all cards into one pile.

    Challenges

    Entry 4: -----------------------------------------------------------------

    Date: January 16th
    Start Time: 3:30pm
    Duration: 1.25 hours

    We met before class to try to come up with a new idea that we could discuss with Dr. Walter before or after class. Brandan suggested a gesture-based music controller that could change volume, skip songs, etc. We also had the idea of changing the guitar amplifier to a more unique effect involving a device that is put onto the guitar and reacts to movement. To get inspiration, we looked through youtube channels Stuff Made Here and Mark Rober. One video that we liked was a rock paper scissors robot that would always win by recognizing your gesture before your hand was fully down and throwing the winning hand: https://www.youtube.com/watch?v=Twn_4AW0M6U&t=998s. This gave us the idea of a robot that would always win games, and I suggested a card shuffler that would control who could win a game of poker. I was inspired by a youtube comment I recently saw that accused casinos of using this technology in their card shufflers. You could create humorous poker scenarios in which one player thinks they are winning until the last card is revealed and somebody has four 2s. We presented the idea to Shivam, and he told us somebody did the same thing 2 years ago, so it definitely fit the course requirements. The previous team failed due to mechanical problems.

    We spoke with Dr. Walter after class, and he told us more about the other team’s design. They used a wheel to hold all 52 cards.

    Entry 2: -----------------------------------------------------------------

    Date: January 15th
    Start Time: 9:30am
    Duration: 2 hours

    Our first manlab section. We continued discussion of which idea we wanted to pursue. It was more clear that neither idea was being fully supported by all members. The braille idea seemed to be difficult mechanically and only useful in extremely niche scenarios, while the guitar amplifier seemed done before, not that exciting on a resume, and only interesting to Brendan and me. Johnny brought up a fun project that Mark Rober did: a remote control bowling ball. https://www.youtube.com/watch?v=wM5NHC97JBw. We all agreed that this is the kind of project we want to do, but we don’t want to directly copy a famous project, and it would be hard to test in the lab space.

    We presented both of our ideas to the TAs and told them we weren’t sure which we would do and we are still looking for a new idea. We will brainstorm tonight and meet before class tomorrow to decide on ideas that are more similar to the bowling ball.

    Entry 1: -----------------------------------------------------------------

    Date: January 14th
    Start Time: 5:30om
    Duration: .5 hours

    After class, we regrouped after not speaking over break. After having time to reflect, Johnny and Krish realized that they weren’t very interested in the guitar amplifier idea. It wouldn’t be very attractive to demonstrate or on a resume, and a lot of the difficulty would come down to digital signal processing, which isn’t a very exciting group activity. We briefly debated between keeping the same idea and going back to Krish’s idea from the fall, which was a smart braille learning display with LLM integration. We decided we would talk to the TAs the following day about whether we could switch and would try to brainstorm other possibilities.