Motor Lab
Materials
In this laboratory we will use the Motor Hat developed by Adafruit: https://www.adafruit.com/products/2348 which has a detailed tutorial https://learn.adafruit.com/adafruit-dc-and-stepper-motor-hat-for-raspberry-pi
The main components of the hat are power electronics to drive currents into motors and an integrated circuit to create pulses. The motor driver (TB6612) takes up to 15V and can deliver 1.2A of current and can control two DC motors with an H-bridge. There are two motor drivers on the hat resulting in up to 4 DC motors or 2 bipolar stepper motors. The PWM driver (PCA9685) creates precise pulses to control the speed of DC motors or the rotation of stepper motors or the orientation of a servo motor. The Raspberry Pi could create such pulses on the digital output pins but depending on the CPU usage from other applications, the pulse precision varies. A dedicated chip guarantees precise timing. The Raspberry Pi communicates to the PWM driver with I2C. 12 channels of the PWM driver are used to create signals for the motor drivers and 4 channels are available to control servo motors (0,1,14,15).
We have two types of motor hats. One operates at i2c address 0x60 the other 0x6F/0x70.
Sometimes the Adafruit Motor hats are out of stock and the clones on AliExpress will take 2 weeks to ship. If you short the motor hat, it might become difficult to complete the lab on time.
Assembly and Installation of Motorhat
Make sure you covered exposed wires on the back of the Motorhat with electrical tape.
If the extension header pins are bent, use pliers and carefully bend them back. Ask for instructor help if needed.
Do not power up the Raspberry Pi with the Motor Hat installed without having the standoff screws in place!
Make sure power wires are all the way in the screw in terminal so that they can not short. Cut them to appropriate length.
Likely your Motorhat is already assembled, so you can skip the followng section below.
The motor-hat does not have its connectors attached. We will need to attach the 40 pin connector to the Raspberry Pi, the screw in terminals and pins for 5V, GND, and the PWM outputs. It is critical that you solder those pins onto the chip precisely and do not use too much solder, otherwise you will not be able to connect other parts to the pins.
Do NOT use the provided 40 pin connector. Use the custom 40 pin connector that allows you to stack a second hat onto the motor-hat. It is very tedious to de-solder 40 pins if you used the wrong connector. If you mount the parts incorrectly, I will ask you to order a replacement hat. Based on pictures on the Adafruit website it should be pretty clear which side of the board points upwards and which connector goes where.
There are also standoffs that have the correct length to attach the board properly to the Raspberry Pi.
The pins can NOT have solder on them along at least the top 2/3 of the pin. When you make the solder connections do the following:
Make sure your solder tip is clean and shiny. Do not use a file or sandpaper to clean it. Use the metal sponge.
Insert the connector and place the parts onto a flat surface making sure they are mounted perpendicular.
Solder one pin on one side and on the opposite side of the connector to fasten the connector to the Raspberry Pi. Inspect the placement and make adjustments if necessary. Only then start soldering all the other connections. As soon as you have more than two solder joints you will not be able to make adjustments to the connector placement anymore.
When soldering make sure you heat both the pad and the pin with the tip by pushing against both and having the solder tip at a 45 degree angle in between the pin and the pad. The iron should point from the long side to towards the board and perpendicular to the edge of the board. For the lower row it should point to the outside of the board.
Feed the solder from the opposite side of the iron tip and feed it exactly the same way each time you make a connection. The solder will melt if the pin and pad is hot enough.
Always take back the solder wire first and then the solder iron.
Do NOT dab with the solder iron! Either place it onto the component, heat the pin and pad or retract the solder iron tip. Do not go forth and back multiple times. If there was not enough solder repeat the process.
Regularly clean the solder iron tip.
You will also need to place 4 pins to the PWM output 0,1,14,15 and 4 times 3 pins to the 5V, GND and 3V lines as well as the screw in terminals.
The screw in terminals come in 3 connector and 2 connector types. In order to create a 5 pin screw in terminal you need to slide a 2 pin and a 3 pin terminal into each other. It will take a close look to figure out how the plastic housings can be mated.
Software
To install the motor library use the following commands. Like for the humidity and pressure sensor, this library depends on Adafruit GPIO and Adafruit simpleIO library which should already be installed. There is newer blinka compatible driver but that driver does not support the servo motors.
# Activate your environment
cd ~/pythonBME210
source env/bin/activate
# You might have the wrong board version installed
pip3 uninstall board
# Install the modules -------------------------------------------
pip3 install adafruit-circuitpython-typing
# Make sure Blinka is latest version
pip3 install --upgrade --force-reinstall Adafruit-Blinka
# Get the motor modules
pip3 install adafruit-circuitpython-pca9685
pip3 install adafruit-circuitpython-motor
pip3 install adafruit-circuitpython-motorkit
# Get a copy of the example programs
git clone https://github.com/adafruit/Adafruit_CircuitPython_Motor
git clone https://github.com/adafruit/Adafruit_CircuitPython_PCA9685
git clone https://github.com/adafruit/Adafruit_CircuitPython_MotorKit
git clone https://github.com/uutzinger/meArmPi.git
And please note that your Motor Hat might have different address. You can find it using:
sudo i2cdetect -y 1
Servo Motor Setup
Do not power up the Raspberry Pi with the Motor Hat installed without having the standoff screws in place!
Make sure power wires are all the way in the screw in terminal so that they can not short. Strip them to appropriate length.
How does Servo Motor work?: https://www.sparkfun.com/servos
Connections:
+ you will need to connect your Power Supply red connector to the power input of the motor-hat.
- you will need to connect your Power Supply black connector to the power input of the motor-hat.
Use black and red stranded wire and connect it to the power input of the motor-hat. Set the programmable power supply in the lab to 5V and verify that it provides 5V between the red and the black banana connectors. Connect the wires from the motor-hat to the output of the power supply using the screw terminals and the power supplies screw on covers of the banana connectors.
Take the motor wires and connect them to the to a PWM servo port . On the servo motor, GND is black/brown, 5V is red and the PWM signal goes into the white/yellow signal cable. Verify that the motor is connected properly.
Software
Please check the examples in https://github.com/adafruit/Adafruit_CircuitPython_Motor/tree/main/examples. We have the PCA9685 Pulse Generator. The channels 0, 1, 14 and 15 are available to control Servos. The examples use channel 7 which is not available to us.
The PWM frequency should be at 50Hz (20milli seconds).
A good minimum pulse is 500 and good max is 2500 micro seconds. Those are the end positions of the motor axle.
The simplest code likely looks like this (let staff know if this does not work):
import time
from board import SCL, SDA
import busio
from adafruit_pca9685 import PCA9685
from adafruit_motor import servo
i2c = busio.I2C(SCL, SDA)
pca = PCA9685(i2c, address=0x40)
pca.frequency = 50
servo0 = servo.Servo(pca.channels[0], min_pulse=580, max_pulse=2350)
for i in range(180):
servo0.angle = i
time.sleep(0.03)
for i in range(180):
servo0.angle = 180 - i
time.sleep(0.03)
pca.deinit()
Stepper Motor Setup
Do not power up the Raspberry Pi with the Motor Hat installed without having the standoff screws in place!
Make sure power wires are all the way in the screw in terminal so that they can not short. Strip them to appropriate length.
Make sure the motor wires are all the way in the screw in terminal so that they can not short. Strip them to appropriate length.
Remove the Servo Motor from the Motor Hat. You can not run both Motors on the same hat.
How does a Stepper Motor work:
https://en.wikipedia.org/wiki/Stepper_motor
Hook up:
We have a bi-polar stepper motors that run at up to 10V but will also run at 5V. It has 200 steps per revolution (instructor will need to verify). The NEMA17 StepperOnline P/N 17HS15-1504S motor has two coils.
Black, goes to motor 1 (M1) on the hat
Green, goes to motor 1 (M1) on the hat
Blue, goes to motor 2 (M2) on the hat
Red, goes to motor 2 (M2) on the hat
M3 and M4 would work also. Do not connect to the middle GND terminal. To attach the motor you can use male-male jumper cables. To make sure the cables don't fall out of the connector, you can keep them in place with tape.
Software:
Stepper Motor test code is at https://github.com/adafruit/Adafruit_CircuitPython_MotorKit in the examples folder.
DC Motor
Do not power up the Raspberry Pi with the Motor Hat installed without having the standoff screws in place!
Make sure power wires are all the way in the screw in terminal so that they can not short. Strip them to appropriate length.
Make sure the motore wires all all the way in the screw in terminal so that they can not sort. Strip them to appropriate length.
Remove Servo Motor from the Motor Hat. You can not run both Motors on the same hat.
How does DC Motor work:
https://en.wikipedia.org/wiki/DC_motor
Hook up guide:
The raspberry pi pinout can be seen by running the command pinout in the terminal or in this image: https://cdn.sparkfun.com/assets/learn_tutorials/4/2/4/header_pinout.jpg
DO NOT JUST PLUG IN SOMEWHERE, MAKE AN EDUCATED CHOICE.
DO NOT COPY YOUR NEIGHBOR's SETUP. (you dont learn anything and you might fry two motor encoders)
The micro DC Motor is a 6V motor with an attached transmission and free running at 75 rotations per minute (RPM). It has a two Hall rotation encoders giving 7 pulsed per motor rotation and xx? pulses per shaft rotation.
You will need to solder jumper wires onto the cable that is attached to the motor. Use shrink tubing to cover the solder joint.
Black: encoder power supply +3.3V, if you hook this up wrong your motor encoder will be dead. This goes to raspberry pi 3.3V output. The hook up wore needs a female terminal.
Yellow: signal feedback (7 pulses when the motor rotates for one circle). This goes to any input pins on the raspberry pi except I2C and power pins. The hookup wire needs a female terminal.
Green: signal feedback (7 pulses when the motor rotates for one circle but shifted 90 degrees). This goes to any input pins if the raspberry pi except the I2C and power pins. The hookup wire needs a female terminal.
Blue: encoder power supply GND (the positive and negative poles cannot be connected incorrectly). This goes to raspberry pi GND. The hookup wire needs a female terminal
Red: Motor power supply. This needs a male hoop terminal and goes to the motor hat M1,2,3 or 4.
White: Motor power supply. This needs a male hook up terminal and goes to the motor hat M1,2,3 or 4, but needs to be the same Motor channel as the red wire.
We will power the encoder with 3.3 V from Raspberry Pi (black wire) and read the yellow and green wire with an input pin (e.g. pin 40 which is GPIO21). Ground could be pin 39 on the other side of pin 40 (blue). Any input pin will work for signal input except the I2C and SPI pins. You need to check the pinout diagram of the raspberry pi above. Dimensions and connections are shown here: https://www.aliexpress.us/item/3256804813215103.html?spm=a2g0o.order_list.order_list_main.29.46e718023Fx0c3&gatewayAdapt=glo2usa
[Not used] The short DC Motor is a 6-12V motor with an attached transmission 1:110, free running at 64 rotations per minute (RPM). It has a single Hall rotation encoder giving one pulse per motor rotation and 110 pulses per shaft revolution. The power to the motor is connected to the orange and blue wire. The encoder receives its 3.3V on the red wire and ground on the black wire. The position signal is provided on the white wire. We will power the encoder with 3.3 V from Raspberry Pi (pin 1) and read the white wire with an input pin (e.g. pin 40 which is GPIO21). Ground could be pin 39 on the other side of pin 40. Any input pin will work for signal input except I2C and SPI pins. You need to check the pinout diagram of the raspberry pi above. Dimensions and connections are shown here: https://www.aliexpress.com/item/33008547634.html?spm=a2g0s.9042311.0.0.3dfa4c4dtX3HRJ
Image below on the right is for short DC motor with encoder.
[Not used] The longer DC Motor is JGA25-370 that runs at 6-12V input with an attached transmission 1:20.4, free running at 190 (6V) up to 350 (12) RPM. It has a quadrature position encoder giving 11 pulses per revolution and on the output shaft 224.4 pulses per revolution. The wiring differs on some of the encoders. We have the red colored circuit board attached to the motor. There the power to the motor is connected to the outermost wires (white and red) and need to be connected to M3. Black and Blue are power to encoder electronics and require 3.3V on blue and black being GND. Yellow and Green are the pulses indicating a rotation. Its possible to determine forward backward rotation by comparing the pulses on yellow and green. An other version of this motor (green PCB) uses this encoder design: https://sc01.alicdn.com/kf/HTB1e6dRGpXXXXctaXXXq6xXFXXX3/200666655/HTB1e6dRGpXXXXctaXXXq6xXFXXX3.jpg.
Encoder:
The first encoder Image below in the middle is for long DC motor with encoder.
The second image below is for the micro DC motor encoder.
Connect one of the encoder signals to a raspberry pi input pin. Any input pin except I2C and SPI will work. You need to check the raspberry pi pinout to make sure you hook up the encoder signal and power 3.3V and GND to the right pins on the raspberry pi header. Do NOT connect to 5V and do not connect the encoder output to 5V or GND please.
Software:
Some example code to count the pulses is below. You will need to turn the motor by hand to observe that the counts increasing. If this does not work, check with staff.
The speed of the motor is counts per second. I believe you will receive 7 pulses for one rotation.
The motor examples from adafruit-circuitpython-motorkit should be used to complete this code. The other examples are not specifically made for the motor hat.
Make a graph that shows the speed (rotations per second) of the motor versus the motor "power" value. You can adjust the pulse width of the motor to change the power going into the motor. 100% is always on. 50% is half the time on.
Consider writing a loop with power changing from 0 to 255. Each iteration in your loop you should give the motor some time to run otherwise the counter will not increment. Your motor will continue running if you are not releasing it, so perhaps at the end of the loop you will set speed to 0 or turn off the motor.
# Setup
##########################################
import RPi.GPIO as GPIO # what is this for?
import time
# you need to import motor related functions
from Ada ...
# Counter Service Routine
##########################################
# Independent piece of code that is run when event occurs.
# Main program stops, and this is executed and then the
# computer goes back to the main program
def myCallback(pin):
global counter
counter+=1
# Counter Setup
##########################################
encoderPin = 21 # this is the number of GPIO pin, e.g. GPIO21 is located on pin 40
counter = 0
GPIO.setmode(GPIO.BCM) # this depends on type or raspberry pi
GPIO.setup(encoderPin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # why do we need pullup?
# setup the pin to count and attach the callback function to this pin
GPIO.add_event_detect(encoderPin, GPIO.RISING, callback=myCallback)
# Motor Setup
##########################################
# Motor setup here
#
# Check in https://github.com/adafruit/Adafruit_CircuitPython_MotorKit
# for the DC motor example code.
#
# This section you will need to implement for your final code.
# You do not need to write this code just for testing the encoder as
# you can run this code without the motor and turn the axle by hand
# to test the encoder.
#
# 1) Motor Power/Speed/Throttle statement
# 2) Release statement
# 3) Direction statement
# CSV file setup
##########################################
# you want to create a file into which you will write the data
# Main Program
##########################################
# if you are just testing the encoder:
while True:
# for the final program you will want to use:
# for power in range(0,255,5):
# set motor power Here, Do not exceed 255. You will want to loop through values.
# motor power command goes here
time.sleep(0.5) # how long do you think it takes until the motor has reached the new speed?
#Let motor spin at set power and measure counts.
previousCounter = counter
previousTime = time.time()
time.sleep(1)
currentCounter = counter
currentTime = time.time()
# The next line will not work unless you provide the correct variables
# delta X is the change of motor position since last time
# delta T is the time between now and the last time
print("Speed: %f" %(delta-x/delta-t) )
# Now you will want to write into the CSV file
# stop the motor and close the motor object
Troubleshooting
It is possible that the motor hat becomes unresponsive. The python library will open up correctly and i2cdetect command shows that its connected, but the motors do not work.
This will require powering down the motor hat and booting it up again (unplug external power supply). It might also require that you power down (shutdown and unplug) the raspberry pi.
You should be able to test the motor hat by running the servo motor program you made as those motors take least amount of effort to connect.
Writing CSV File
If you want to import your data into Excel you should save it in a "comma separated value" file.
Please read csv documentation of python: https://docs.python.org/3/library/csv.html
This line in the document sounds really good to me: "The corresponding simplest possible writing example is: " .....
Then the question is what is an iterable? Examples are lists or combining the two variables setspedd and measuredspeed into a list like: setspeed, measuredspeed].
Likely writerow expects the iterable to be a string. You can convert to string using "{}".format(value) you can set the format precision with {:.2f}
Please repalce
with open('some.csv', 'w', newline='') as f:
writer = csv.writer(f)
with
f = open('some.csv', 'w', newline='')
writer = csv.writer(f)
and place it outside the loop so that the file does not need to be opened each time you want to write to it. Then you would need to close the file after you finished with the loop with
f.close()
otherwise some of the data will not be written to the file and it might be incomplete or empty.
When you use the with statement, it automatically closes the file when with is finished. When you close the file and want to add data you will want to open the file using 'a' for append instead of 'w' which stands for write. If you write to the file with having file opened outside the loop, you would not need to append as the file remains open until the loop is completed.
Turn In
Please show the DC Motor, Servo and Stepper motors working. They can not run at the same time, so you will need to show the TA, ULAs or instructors each time.
Collect DC motor data by measuring the pulses per second at a variety of power settings (From 0 to 255 or in the newer library from 0 to 1 (=100%)). Please create a simple graph of the set power/speed vs measured speed (include axis labels and title, units etc.).
This requires you to use example software from https://github.com/adafruit/Adafruit_CircuitPython_MotorKit and the code example above to modify it with the call back routine for counting the encoding pulses. The key element for a call back that simply counts the pulses is above. Pin is the pin on the raspberry you used to count the pulses.
To summarize, you will need to develop a code using the example code above as well as the example code on Github. This code needs to set the power/speed/throttle of the DC motor and also mathematically calculate the speed at which the motor is actually rotating. This code will increment the power/speed/throttle from 0 to 255 (or 1) and accompanying measured speeds will be calculated at each set speed.
When you set the power/speed/throttle it will take the motor some time to speed up. So wait a little bit before you measure the speed.
Each of these data points need to be added to a new line in a csv file to store the data and graph it for the report. The final graph should look similar to this with axis labels, units, a trendline, and an equation included as well.
Use this report outline for your lab submission. Answer the questions and put in the graphs/screenshots.