Update
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
########################################################################
|
||||
from gpiozero import LEDBoard
|
||||
from time import sleep
|
||||
from signal import pause
|
||||
|
||||
print ('Program is starting ... ')
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : Hello.py
|
||||
# Description : Print "Hello World!".
|
||||
# auther : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
|
||||
def Hello():
|
||||
print('Hello World!')
|
||||
|
||||
Hello()
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : Blink.py
|
||||
# Description : Basic usage of GPIO. Let led blink.
|
||||
# auther : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
from gpiozero import LED
|
||||
from time import sleep
|
||||
|
||||
led = LED(17) # define LED pin according to BCM Numbering
|
||||
#led = LED("J8:11") # BOARD Numbering
|
||||
'''
|
||||
# pins numbering, the following lines are all equivalent
|
||||
led = LED(17) # BCM
|
||||
led = LED("GPIO17") # BCM
|
||||
led = LED("BCM17") # BCM
|
||||
led = LED("BOARD11") # BOARD
|
||||
led = LED("WPI0") # WiringPi
|
||||
led = LED("J8:11") # BOARD
|
||||
'''
|
||||
def loop():
|
||||
while True:
|
||||
led.on() # turn on LED
|
||||
print ('led turned on >>>') # print message on terminal
|
||||
sleep(1) # wait 1 second
|
||||
led.off() # turn off LED
|
||||
print ('led turned off <<<') # print message on terminal
|
||||
sleep(1) # wait 1 second
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting ... \n')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : ButtonLED.py
|
||||
# Description : Control led with button.
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
from gpiozero import LED, Button
|
||||
|
||||
led = LED(17) # define LED pin according to BCM Numbering
|
||||
button = Button(18) # define Button pin according to BCM Numbering
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
if button.is_pressed: # if button is pressed
|
||||
led.on() # turn on led
|
||||
print("Button is pressed, led turned on >>>") # print information on terminal
|
||||
else : # if button is relessed
|
||||
led.off() # turn off led
|
||||
print("Button is released, led turned off <<<")
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : Tablelamp.py
|
||||
# Description : DIY MINI table lamp
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
from gpiozero import LED, Button
|
||||
import time
|
||||
|
||||
led = LED(17) # define LED pin according to BCM Numbering
|
||||
button = Button(18) # define Button pin according to BCM Numbering
|
||||
|
||||
def onButtonPressed(): # When button is pressed, this function will be executed
|
||||
led.toggle()
|
||||
if led.is_lit :
|
||||
print("Led turned on >>>")
|
||||
else :
|
||||
print("Led turned off <<<")
|
||||
def loop():
|
||||
#Button detect
|
||||
button.when_pressed = onButtonPressed
|
||||
while True:
|
||||
time.sleep(1)
|
||||
def destroy():
|
||||
led.close()
|
||||
button.close()
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : LightWater.py
|
||||
# Description : Use LEDBar Graph(10 LED)
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
from gpiozero import LEDBoard
|
||||
from time import sleep
|
||||
|
||||
#ledPins = ["J8:11", "J8:12","J8:13","J8:15","J8:16","J8:18","J8:22","J8:3","J8:5","J8:24"]
|
||||
ledPins = [17, 18, 27, 22, 23, 24, 25, 2, 3, 8]
|
||||
|
||||
leds = LEDBoard(*ledPins, active_high=False)
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
for index in range(0,len(ledPins),1): # make led(on) move from left to right
|
||||
leds.on(index)
|
||||
sleep(0.1)
|
||||
leds.off(index)
|
||||
for index in range(len(ledPins)-1,-1,-1): #move led(on) from right to left
|
||||
leds.on(index)
|
||||
sleep(0.1)
|
||||
leds.off(index)
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
print("Ending program")
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : BreathingLED.py
|
||||
# Description : Breathing LED
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
from gpiozero import PWMLED
|
||||
import time
|
||||
|
||||
led = PWMLED(18 ,initial_value=0 ,frequency=1000)
|
||||
def loop():
|
||||
while True:
|
||||
for b in range(0, 101, 1): # make the led brighter
|
||||
led.value = b / 100.0 # set dc value as the duty cycle
|
||||
time.sleep(0.01)
|
||||
time.sleep(1)
|
||||
for b in range(100, -1, -1): # make the led darker
|
||||
led.value = b / 100.0 # set dc value as the duty cycle
|
||||
time.sleep(0.01)
|
||||
time.sleep(1)
|
||||
def destroy():
|
||||
led.close()
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting ... ')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : ColorfulLED.py
|
||||
# Description : Random color change ColorfulLED
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
from gpiozero import RGBLED
|
||||
import time
|
||||
import random
|
||||
|
||||
#led = RGBLED(red="J8:11", green="J8:12", blue="J8:13", active_high=False) # define the pins for R:11,G:12,B:13
|
||||
led = RGBLED(red=17, green=18, blue=27, active_high=False) # define the pins for R:GPIO17,G:GPIO18,B:GPIO27
|
||||
# If your RGBLED is a common cathode LED, set active_high to True
|
||||
|
||||
def setColor(r_val,g_val,b_val): # change duty cycle for three pins to r_val,g_val,b_val
|
||||
led.red=r_val/100 # change pwmRed duty cycle to r_val
|
||||
led.green = g_val/100 # change pwmRed duty cycle to r_val
|
||||
led.blue = b_val/100 # change pwmRed duty cycle to r_val
|
||||
|
||||
def loop():
|
||||
while True :
|
||||
r=random.randint(0,100) #get a random in (0,100)
|
||||
g=random.randint(0,100)
|
||||
b=random.randint(0,100)
|
||||
setColor(r,g,b) #set random as a duty cycle value
|
||||
print ('r=%d, g=%d, b=%d ' %(r ,g, b))
|
||||
time.sleep(1)
|
||||
|
||||
def destroy():
|
||||
led.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting ... ')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : Doorbell.py
|
||||
# Description : Make doorbell with buzzer and button
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
from gpiozero import Buzzer, Button
|
||||
import time
|
||||
|
||||
buzzer = Buzzer(17)
|
||||
button = Button(18)
|
||||
|
||||
def onButtonPressed():
|
||||
buzzer.on()
|
||||
print("Button is pressed, buzzer turned on >>>")
|
||||
|
||||
def onButtonReleased():
|
||||
buzzer.off()
|
||||
print("Button is released, buzzer turned on <<<")
|
||||
|
||||
def loop():
|
||||
button.when_pressed = onButtonPressed
|
||||
button.when_released = onButtonReleased
|
||||
while True :
|
||||
time.sleep(1)
|
||||
|
||||
def destroy():
|
||||
buzzer.close()
|
||||
button.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting ... ')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : Alertor.py
|
||||
# Description : Make Alertor with buzzer and button
|
||||
# Author : www.freenove.com
|
||||
# modification: 2019/12/27
|
||||
########################################################################
|
||||
from gpiozero import TonalBuzzer,Button
|
||||
from gpiozero.tones import Tone
|
||||
import time
|
||||
import math
|
||||
|
||||
buzzer = TonalBuzzer(17)
|
||||
button = Button(18) # define Button pin according to BCM Numbering
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
if button.is_pressed: # if button is pressed
|
||||
alertor()
|
||||
print ('alertor turned on >>> ')
|
||||
else :
|
||||
stopAlertor()
|
||||
print ('alertor turned off <<<')
|
||||
def alertor():
|
||||
for x in range(0,361): # Make frequency of the alertor consistent with the sine wave
|
||||
sinVal = math.sin(x * (math.pi / 180.0)) # calculate the sine value
|
||||
toneVal = 2000 + sinVal * 500 # Add to the resonant frequency with a Weighted
|
||||
b.play(Tone(toneVal)) # Change Frequency of PWM to toneVal
|
||||
time.sleep(0.001)
|
||||
|
||||
def stopAlertor():
|
||||
buzzer.stop()
|
||||
|
||||
def destroy():
|
||||
buzzer.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : ADC.py
|
||||
# Description : Use ADC module to read the voltage value of potentiometer.
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
import time
|
||||
from ADCDevice import *
|
||||
|
||||
adc = ADCDevice() # Define an ADCDevice class object
|
||||
|
||||
def setup():
|
||||
global adc
|
||||
if(adc.detectI2C(0x48)): # Detect the pcf8591.
|
||||
adc = PCF8591()
|
||||
elif(adc.detectI2C(0x4b)): # Detect the ads7830
|
||||
adc = ADS7830()
|
||||
else:
|
||||
print("No correct I2C address found, \n"
|
||||
"Please use command 'i2cdetect -y 1' to check the I2C address! \n"
|
||||
"Program Exit. \n");
|
||||
exit(-1)
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
value = adc.analogRead(0) # read the ADC value of channel 0
|
||||
voltage = value / 255.0 * 3.3 # calculate the voltage value
|
||||
print ('ADC Value : %d, Voltage : %.2f'%(value,voltage))
|
||||
time.sleep(0.1)
|
||||
|
||||
def destroy():
|
||||
adc.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting ... ')
|
||||
try:
|
||||
setup()
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : ADCDevice.py
|
||||
# Description : Freenove ADC Module library.
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
|
||||
import smbus
|
||||
|
||||
class ADCDevice(object):
|
||||
def __init__(self):
|
||||
self.cmd = 0
|
||||
self.address = 0
|
||||
self.bus=smbus.SMBus(1)
|
||||
# print("ADCDevice init")
|
||||
|
||||
def detectI2C(self,addr):
|
||||
try:
|
||||
self.bus.write_byte(addr,0)
|
||||
print("Found device in address 0x%x"%(addr))
|
||||
return True
|
||||
except:
|
||||
print("Not found device in address 0x%x"%(addr))
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
self.bus.close()
|
||||
|
||||
class PCF8591(ADCDevice):
|
||||
def __init__(self):
|
||||
super(PCF8591, self).__init__()
|
||||
self.cmd = 0x40 # The default command for PCF8591 is 0x40.
|
||||
self.address = 0x48 # 0x48 is the default i2c address for PCF8591 Module.
|
||||
|
||||
def analogRead(self, chn): # PCF8591 has 4 ADC input pins, chn:0,1,2,3
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
return value
|
||||
|
||||
def analogWrite(self,value): # write DAC value
|
||||
self.bus.write_byte_data(address,cmd,value)
|
||||
|
||||
class ADS7830(ADCDevice):
|
||||
def __init__(self):
|
||||
super(ADS7830, self).__init__()
|
||||
self.cmd = 0x84
|
||||
self.address = 0x4b # 0x4b is the default i2c address for ADS7830 Module.
|
||||
|
||||
def analogRead(self, chn): # ADS7830 has 8 ADC input pins, chn:0,1,2,3,4,5,6,7
|
||||
value = self.bus.read_byte_data(self.address, self.cmd|(((chn<<2 | chn>>1)&0x07)<<4))
|
||||
return value
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : ADCDevice.py
|
||||
# Description : Freenove ADC Module library.
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
|
||||
import smbus
|
||||
|
||||
class ADCDevice(object):
|
||||
def __init__(self):
|
||||
self.cmd = 0
|
||||
self.address = 0
|
||||
self.bus=smbus.SMBus(1)
|
||||
# print("ADCDevice init")
|
||||
|
||||
def detectI2C(self,addr):
|
||||
try:
|
||||
self.bus.write_byte(addr,0)
|
||||
print("Found device in address 0x%x"%(addr))
|
||||
return True
|
||||
except:
|
||||
print("Not found device in address 0x%x"%(addr))
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
self.bus.close()
|
||||
|
||||
class PCF8591(ADCDevice):
|
||||
def __init__(self):
|
||||
super(PCF8591, self).__init__()
|
||||
self.cmd = 0x40 # The default command for PCF8591 is 0x40.
|
||||
self.address = 0x48 # 0x48 is the default i2c address for PCF8591 Module.
|
||||
|
||||
def analogRead(self, chn): # PCF8591 has 4 ADC input pins, chn:0,1,2,3
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
return value
|
||||
|
||||
def analogWrite(self,value): # write DAC value
|
||||
self.bus.write_byte_data(address,cmd,value)
|
||||
|
||||
class ADS7830(ADCDevice):
|
||||
def __init__(self):
|
||||
super(ADS7830, self).__init__()
|
||||
self.cmd = 0x84
|
||||
self.address = 0x4b # 0x4b is the default i2c address for ADS7830 Module.
|
||||
|
||||
def analogRead(self, chn): # ADS7830 has 8 ADC input pins, chn:0,1,2,3,4,5,6,7
|
||||
value = self.bus.read_byte_data(self.address, self.cmd|(((chn<<2 | chn>>1)&0x07)<<4))
|
||||
return value
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : ADC.py
|
||||
# Description : Use ADC module to read the voltage value of potentiometer.
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
from gpiozero import PWMLED
|
||||
import time
|
||||
from ADCDevice import *
|
||||
|
||||
led = PWMLED(17,frequency=1000) # define LED pin according to BCM Numbering
|
||||
adc = ADCDevice() # Define an ADCDevice class object
|
||||
|
||||
def setup():
|
||||
global adc
|
||||
if(adc.detectI2C(0x48)): # Detect the pcf8591.
|
||||
adc = PCF8591()
|
||||
elif(adc.detectI2C(0x4b)): # Detect the ads7830
|
||||
adc = ADS7830()
|
||||
else:
|
||||
print("No correct I2C address found, \n"
|
||||
"Please use command 'i2cdetect -y 1' to check the I2C address! \n"
|
||||
"Program Exit. \n");
|
||||
exit(-1)
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
value = adc.analogRead(0) # read the ADC value of channel 0
|
||||
led.value = value / 255.0 # Mapping to PWM duty cycle
|
||||
voltage = value / 255.0 * 3.3 # calculate the voltage value
|
||||
print ('ADC Value : %d, Voltage : %.2f'%(value,voltage))
|
||||
time.sleep(0.03)
|
||||
|
||||
def destroy():
|
||||
led.close()
|
||||
adc.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting ... ')
|
||||
try:
|
||||
setup()
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : ADCDevice.py
|
||||
# Description : Freenove ADC Module library.
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
|
||||
import smbus
|
||||
|
||||
class ADCDevice(object):
|
||||
def __init__(self):
|
||||
self.cmd = 0
|
||||
self.address = 0
|
||||
self.bus=smbus.SMBus(1)
|
||||
# print("ADCDevice init")
|
||||
|
||||
def detectI2C(self,addr):
|
||||
try:
|
||||
self.bus.write_byte(addr,0)
|
||||
print("Found device in address 0x%x"%(addr))
|
||||
return True
|
||||
except:
|
||||
print("Not found device in address 0x%x"%(addr))
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
self.bus.close()
|
||||
|
||||
class PCF8591(ADCDevice):
|
||||
def __init__(self):
|
||||
super(PCF8591, self).__init__()
|
||||
self.cmd = 0x40 # The default command for PCF8591 is 0x40.
|
||||
self.address = 0x48 # 0x48 is the default i2c address for PCF8591 Module.
|
||||
|
||||
def analogRead(self, chn): # PCF8591 has 4 ADC input pins, chn:0,1,2,3
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
return value
|
||||
|
||||
def analogWrite(self,value): # write DAC value
|
||||
self.bus.write_byte_data(address,cmd,value)
|
||||
|
||||
class ADS7830(ADCDevice):
|
||||
def __init__(self):
|
||||
super(ADS7830, self).__init__()
|
||||
self.cmd = 0x84
|
||||
self.address = 0x4b # 0x4b is the default i2c address for ADS7830 Module.
|
||||
|
||||
def analogRead(self, chn): # ADS7830 has 8 ADC input pins, chn:0,1,2,3,4,5,6,7
|
||||
value = self.bus.read_byte_data(self.address, self.cmd|(((chn<<2 | chn>>1)&0x07)<<4))
|
||||
return value
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
#############################################################################
|
||||
# Filename : Softlight.py
|
||||
# Description : Control RGBLED with Potentiometer
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
from gpiozero import RGBLED
|
||||
import time
|
||||
from ADCDevice import *
|
||||
|
||||
led = RGBLED(red=22, green=27, blue=17, active_high=False) # define the pins for R:GPIO22,G:GPIO27,B:GPIO17
|
||||
#led = RGBLED(red="J8:15", green="J8:13", blue="J8:11") # according to BOARD Numbering define the pins for R:11,G:12,B:13
|
||||
adc = ADCDevice() # Define an ADCDevice class object
|
||||
|
||||
def setup():
|
||||
global adc
|
||||
if(adc.detectI2C(0x48)): # Detect the pcf8591.
|
||||
adc = PCF8591()
|
||||
elif(adc.detectI2C(0x4b)): # Detect the ads7830
|
||||
adc = ADS7830()
|
||||
else:
|
||||
print("No correct I2C address found, \n"
|
||||
"Please use command 'i2cdetect -y 1' to check the I2C address! \n"
|
||||
"Program Exit. \n");
|
||||
exit(-1)
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
value_Red = adc.analogRead(0) # read ADC value of 3 potentiometers
|
||||
value_Green = adc.analogRead(1)
|
||||
value_Blue = adc.analogRead(2)
|
||||
led.red =value_Red/255 # map the read value of potentiometers into PWM value and output it
|
||||
led.green =value_Green/255
|
||||
led.blue =value_Blue/255
|
||||
# print read ADC value
|
||||
print ('ADC Value value_Red: %d ,\tvlue_Green: %d ,\tvalue_Blue: %d'%(value_Red,value_Green,value_Blue))
|
||||
time.sleep(0.01)
|
||||
|
||||
def destroy():
|
||||
adc.close()
|
||||
led.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting ... ')
|
||||
setup()
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : ADCDevice.py
|
||||
# Description : Freenove ADC Module library.
|
||||
# Author : www.freenove.com
|
||||
# modification: 2020/04/21
|
||||
########################################################################
|
||||
|
||||
import smbus
|
||||
|
||||
class ADCDevice(object):
|
||||
def __init__(self):
|
||||
self.cmd = 0
|
||||
self.address = 0
|
||||
self.bus=smbus.SMBus(1)
|
||||
# print("ADCDevice init")
|
||||
|
||||
def detectI2C(self,addr):
|
||||
try:
|
||||
self.bus.write_byte(addr,0)
|
||||
print("Found device in address 0x%x"%(addr))
|
||||
return True
|
||||
except:
|
||||
print("Not found device in address 0x%x"%(addr))
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
self.bus.close()
|
||||
|
||||
class PCF8591(ADCDevice):
|
||||
def __init__(self):
|
||||
super(PCF8591, self).__init__()
|
||||
self.cmd = 0x40 # The default command for PCF8591 is 0x40.
|
||||
self.address = 0x48 # 0x48 is the default i2c address for PCF8591 Module.
|
||||
|
||||
def analogRead(self, chn): # PCF8591 has 4 ADC input pins, chn:0,1,2,3
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
return value
|
||||
|
||||
def analogWrite(self,value): # write DAC value
|
||||
self.bus.write_byte_data(address,cmd,value)
|
||||
|
||||
class ADS7830(ADCDevice):
|
||||
def __init__(self):
|
||||
super(ADS7830, self).__init__()
|
||||
self.cmd = 0x84
|
||||
self.address = 0x4b # 0x4b is the default i2c address for ADS7830 Module.
|
||||
|
||||
def analogRead(self, chn): # ADS7830 has 8 ADC input pins, chn:0,1,2,3,4,5,6,7
|
||||
value = self.bus.read_byte_data(self.address, self.cmd|(((chn<<2 | chn>>1)&0x07)<<4))
|
||||
return value
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
#############################################################################
|
||||
# Filename : Nightlamp.py
|
||||
# Description : Control LED with Photoresistor
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
from gpiozero import PWMLED
|
||||
import time
|
||||
from ADCDevice import *
|
||||
|
||||
ledPin = 17 # define ledPin
|
||||
led = PWMLED(ledPin)
|
||||
adc = ADCDevice() # Define an ADCDevice class object
|
||||
|
||||
def setup():
|
||||
global adc
|
||||
if(adc.detectI2C(0x48)): # Detect the pcf8591.
|
||||
adc = PCF8591()
|
||||
elif(adc.detectI2C(0x4b)): # Detect the ads7830
|
||||
adc = ADS7830()
|
||||
else:
|
||||
print("No correct I2C address found, \n"
|
||||
"Please use command 'i2cdetect -y 1' to check the I2C address! \n"
|
||||
"Program Exit. \n");
|
||||
exit(-1)
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
value = adc.analogRead(0) # read the ADC value of channel 0
|
||||
led.value = value / 255.0 # Mapping to PWM duty cycle
|
||||
voltage = value / 255.0 * 3.3
|
||||
print ('ADC Value : %d, Voltage : %.2f'%(value,voltage))
|
||||
time.sleep(0.01)
|
||||
|
||||
def destroy():
|
||||
led.close()
|
||||
adc.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting ... ')
|
||||
setup()
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : ADCDevice.py
|
||||
# Description : Freenove ADC Module library.
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
|
||||
import smbus
|
||||
|
||||
class ADCDevice(object):
|
||||
def __init__(self):
|
||||
self.cmd = 0
|
||||
self.address = 0
|
||||
self.bus=smbus.SMBus(1)
|
||||
# print("ADCDevice init")
|
||||
|
||||
def detectI2C(self,addr):
|
||||
try:
|
||||
self.bus.write_byte(addr,0)
|
||||
print("Found device in address 0x%x"%(addr))
|
||||
return True
|
||||
except:
|
||||
print("Not found device in address 0x%x"%(addr))
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
self.bus.close()
|
||||
|
||||
class PCF8591(ADCDevice):
|
||||
def __init__(self):
|
||||
super(PCF8591, self).__init__()
|
||||
self.cmd = 0x40 # The default command for PCF8591 is 0x40.
|
||||
self.address = 0x48 # 0x48 is the default i2c address for PCF8591 Module.
|
||||
|
||||
def analogRead(self, chn): # PCF8591 has 4 ADC input pins, chn:0,1,2,3
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
return value
|
||||
|
||||
def analogWrite(self,value): # write DAC value
|
||||
self.bus.write_byte_data(address,cmd,value)
|
||||
|
||||
class ADS7830(ADCDevice):
|
||||
def __init__(self):
|
||||
super(ADS7830, self).__init__()
|
||||
self.cmd = 0x84
|
||||
self.address = 0x4b # 0x4b is the default i2c address for ADS7830 Module.
|
||||
|
||||
def analogRead(self, chn): # ADS7830 has 8 ADC input pins, chn:0,1,2,3,4,5,6,7
|
||||
value = self.bus.read_byte_data(self.address, self.cmd|(((chn<<2 | chn>>1)&0x07)<<4))
|
||||
return value
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python3
|
||||
#############################################################################
|
||||
# Filename : Thermometer.py
|
||||
# Description : DIY Thermometer
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
import time
|
||||
import math
|
||||
from ADCDevice import *
|
||||
|
||||
adc = ADCDevice() # Define an ADCDevice class object
|
||||
|
||||
def setup():
|
||||
global adc
|
||||
if(adc.detectI2C(0x48)): # Detect the pcf8591.
|
||||
adc = PCF8591()
|
||||
elif(adc.detectI2C(0x4b)): # Detect the ads7830
|
||||
adc = ADS7830()
|
||||
else:
|
||||
print("No correct I2C address found, \n"
|
||||
"Please use command 'i2cdetect -y 1' to check the I2C address! \n"
|
||||
"Program Exit. \n");
|
||||
exit(-1)
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
value = adc.analogRead(0) # read ADC value A0 pin
|
||||
voltage = value / 255.0 * 3.3 # calculate voltage
|
||||
Rt = 10 * voltage / (3.3 - voltage) # calculate resistance value of thermistor
|
||||
tempK = 1/(1/(273.15 + 25) + math.log(Rt/10)/3950.0) # calculate temperature (Kelvin)
|
||||
tempC = tempK -273.15 # calculate temperature (Celsius)
|
||||
print ('ADC Value : %d, Voltage : %.2f, Temperature : %.2f'%(value,voltage,tempC))
|
||||
time.sleep(0.01)
|
||||
|
||||
def destroy():
|
||||
adc.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting ... ')
|
||||
setup()
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : ADCDevice.py
|
||||
# Description : Freenove ADC Module library.
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
|
||||
import smbus
|
||||
|
||||
class ADCDevice(object):
|
||||
def __init__(self):
|
||||
self.cmd = 0
|
||||
self.address = 0
|
||||
self.bus=smbus.SMBus(1)
|
||||
# print("ADCDevice init")
|
||||
|
||||
def detectI2C(self,addr):
|
||||
try:
|
||||
self.bus.write_byte(addr,0)
|
||||
print("Found device in address 0x%x"%(addr))
|
||||
return True
|
||||
except:
|
||||
print("Not found device in address 0x%x"%(addr))
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
self.bus.close()
|
||||
|
||||
class PCF8591(ADCDevice):
|
||||
def __init__(self):
|
||||
super(PCF8591, self).__init__()
|
||||
self.cmd = 0x40 # The default command for PCF8591 is 0x40.
|
||||
self.address = 0x48 # 0x48 is the default i2c address for PCF8591 Module.
|
||||
|
||||
def analogRead(self, chn): # PCF8591 has 4 ADC input pins, chn:0,1,2,3
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
return value
|
||||
|
||||
def analogWrite(self,value): # write DAC value
|
||||
self.bus.write_byte_data(address,cmd,value)
|
||||
|
||||
class ADS7830(ADCDevice):
|
||||
def __init__(self):
|
||||
super(ADS7830, self).__init__()
|
||||
self.cmd = 0x84
|
||||
self.address = 0x4b # 0x4b is the default i2c address for ADS7830 Module.
|
||||
|
||||
def analogRead(self, chn): # ADS7830 has 8 ADC input pins, chn:0,1,2,3,4,5,6,7
|
||||
value = self.bus.read_byte_data(self.address, self.cmd|(((chn<<2 | chn>>1)&0x07)<<4))
|
||||
return value
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
#############################################################################
|
||||
# Filename : Joystick.py
|
||||
# Description : Read Joystick state
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
from gpiozero import Button
|
||||
import time
|
||||
from ADCDevice import *
|
||||
|
||||
Z_Pin = 18 # define Z_Pin
|
||||
button = Button(Z_Pin) # define Button pin according to BCM Numbering
|
||||
adc = ADCDevice() # Define an ADCDevice class object
|
||||
|
||||
def setup():
|
||||
global adc
|
||||
if(adc.detectI2C(0x48)): # Detect the pcf8591.
|
||||
adc = PCF8591()
|
||||
elif(adc.detectI2C(0x4b)): # Detect the ads7830
|
||||
adc = ADS7830()
|
||||
else:
|
||||
print("No correct I2C address found, \n"
|
||||
"Please use command 'i2cdetect -y 1' to check the I2C address! \n"
|
||||
"Program Exit. \n");
|
||||
exit(-1)
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
val_Z = not button.value # read digital value of axis Z
|
||||
val_Y = adc.analogRead(0) # read analog value of axis X and Y
|
||||
val_X = adc.analogRead(1)
|
||||
print ('value_X: %d ,\tvlue_Y: %d ,\tvalue_Z: %d'%(val_X,val_Y,val_Z))
|
||||
time.sleep(0.01)
|
||||
|
||||
def destroy():
|
||||
adc.close()
|
||||
button.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print ('Program is starting ... ') # Program entrance
|
||||
setup()
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : ADCDevice.py
|
||||
# Description : Freenove ADC Module library.
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
|
||||
import smbus
|
||||
|
||||
class ADCDevice(object):
|
||||
def __init__(self):
|
||||
self.cmd = 0
|
||||
self.address = 0
|
||||
self.bus=smbus.SMBus(1)
|
||||
# print("ADCDevice init")
|
||||
|
||||
def detectI2C(self,addr):
|
||||
try:
|
||||
self.bus.write_byte(addr,0)
|
||||
print("Found device in address 0x%x"%(addr))
|
||||
return True
|
||||
except:
|
||||
print("Not found device in address 0x%x"%(addr))
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
self.bus.close()
|
||||
|
||||
class PCF8591(ADCDevice):
|
||||
def __init__(self):
|
||||
super(PCF8591, self).__init__()
|
||||
self.cmd = 0x40 # The default command for PCF8591 is 0x40.
|
||||
self.address = 0x48 # 0x48 is the default i2c address for PCF8591 Module.
|
||||
|
||||
def analogRead(self, chn): # PCF8591 has 4 ADC input pins, chn:0,1,2,3
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
value = self.bus.read_byte_data(self.address, self.cmd+chn)
|
||||
return value
|
||||
|
||||
def analogWrite(self,value): # write DAC value
|
||||
self.bus.write_byte_data(address,cmd,value)
|
||||
|
||||
class ADS7830(ADCDevice):
|
||||
def __init__(self):
|
||||
super(ADS7830, self).__init__()
|
||||
self.cmd = 0x84
|
||||
self.address = 0x4b # 0x4b is the default i2c address for ADS7830 Module.
|
||||
|
||||
def analogRead(self, chn): # ADS7830 has 8 ADC input pins, chn:0,1,2,3,4,5,6,7
|
||||
value = self.bus.read_byte_data(self.address, self.cmd|(((chn<<2 | chn>>1)&0x07)<<4))
|
||||
return value
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
#############################################################################
|
||||
# Filename : Motor.py
|
||||
# Description : Control Motor with L293D
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
from gpiozero import DigitalOutputDevice,PWMOutputDevice
|
||||
import time
|
||||
from ADCDevice import *
|
||||
|
||||
# define the pins connected to L293D
|
||||
motoRPin1 = DigitalOutputDevice(27) # define L293D pin according to BCM Numbering
|
||||
motoRPin2 = DigitalOutputDevice(17) # define L293D pin according to BCM Numbering
|
||||
enablePin = PWMOutputDevice(22,frequency=1000)
|
||||
adc = ADCDevice() # Define an ADCDevice class object
|
||||
|
||||
def setup():
|
||||
global adc
|
||||
if(adc.detectI2C(0x48)): # Detect the pcf8591.
|
||||
adc = PCF8591()
|
||||
elif(adc.detectI2C(0x4b)): # Detect the ads7830
|
||||
adc = ADS7830()
|
||||
else:
|
||||
print("No correct I2C address found, \n"
|
||||
"Please use command 'i2cdetect -y 1' to check the I2C address! \n"
|
||||
"Program Exit. \n");
|
||||
exit(-1)
|
||||
# mapNUM function: map the value from a range of mapping to another range.
|
||||
def mapNUM(value,fromLow,fromHigh,toLow,toHigh):
|
||||
return (toHigh-toLow)*(value-fromLow) / (fromHigh-fromLow) + toLow
|
||||
|
||||
# motor function: determine the direction and speed of the motor according to the input ADC value input
|
||||
def motor(ADC):
|
||||
value = ADC -128
|
||||
if (value > 0): # make motor turn forward
|
||||
motoRPin1.on() # motoRPin1 output HIHG level
|
||||
motoRPin2.off() # motoRPin2 output LOW level
|
||||
print ('Turn Forward...')
|
||||
elif (value < 0): # make motor turn backward
|
||||
motoRPin1.off()
|
||||
motoRPin2.on()
|
||||
print ('Turn Backward...')
|
||||
else :
|
||||
motoRPin1.off()
|
||||
motoRPin2.off()
|
||||
print ('Motor Stop...')
|
||||
b=mapNUM(abs(value),0,128,0,100)
|
||||
enablePin.value = b / 100.0 # set dc value as the duty cycle
|
||||
print ('The PWM duty cycle is %d%%\n'%(abs(value)*100/127)) # print PMW duty cycle.
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
value = adc.analogRead(0) # read ADC value of channel 0
|
||||
print ('ADC Value : %d'%(value))
|
||||
motor(value)
|
||||
time.sleep(0.2)
|
||||
|
||||
def destroy():
|
||||
motoRPin1.close()
|
||||
motoRPin2.close()
|
||||
enablePin.close()
|
||||
adc.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting ... ')
|
||||
setup()
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : Relay.py
|
||||
# Description : Control Relay and Motor via Button
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/15
|
||||
########################################################################
|
||||
from gpiozero import DigitalOutputDevice, Button
|
||||
import time
|
||||
|
||||
relayPin = 17 # define the relayPin
|
||||
buttonPin = 18 # define the buttonPin
|
||||
relay = DigitalOutputDevice(relayPin) # define LED pin according to BCM Numbering
|
||||
button = Button(buttonPin) # define Button pin according to BCM Numbering
|
||||
|
||||
def onButtonPressed(): # When button is pressed, this function will be executed
|
||||
relay.toggle()
|
||||
if relay.value :
|
||||
print("Turn on relay ...")
|
||||
else :
|
||||
print("Turn off relay ... ")
|
||||
|
||||
def loop():
|
||||
button.when_pressed = onButtonPressed
|
||||
while True:
|
||||
time.sleep(1)
|
||||
|
||||
def destroy():
|
||||
relay.close()
|
||||
button.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : Relay.py
|
||||
# Description : Control Relay and Motor via Button
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/15
|
||||
########################################################################
|
||||
from gpiozero import DigitalOutputDevice, Button
|
||||
import time
|
||||
|
||||
relayPin = 17 # define the relayPin
|
||||
buttonPin = 18 # define the buttonPin
|
||||
relay = DigitalOutputDevice(relayPin) # define LED pin according to BCM Numbering
|
||||
button = Button(buttonPin) # define Button pin according to BCM Numbering
|
||||
debounceTime = 50
|
||||
|
||||
def loop():
|
||||
relayState = 0
|
||||
lastChangeTime = round(time.time()*1000)
|
||||
buttonState = 1
|
||||
lastButtonState = 1
|
||||
reading = 1
|
||||
while True:
|
||||
reading = not button.value
|
||||
if reading != lastButtonState :
|
||||
lastChangeTime = round(time.time()*1000)
|
||||
if ((round(time.time()*1000) - lastChangeTime) > debounceTime):
|
||||
if reading != buttonState :
|
||||
buttonState = reading;
|
||||
if buttonState == 0:
|
||||
print("Button is pressed!")
|
||||
relayState = not relayState
|
||||
if relayState:
|
||||
print("Turn on relay ...")
|
||||
else :
|
||||
print("Turn off relay ... ")
|
||||
else :
|
||||
print("Button is released!")
|
||||
relay.on() if (relayState==1) else relay.off()
|
||||
lastButtonState = reading # lastButtonState store latest state
|
||||
|
||||
def destroy():
|
||||
relay.close()
|
||||
button.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : Sweep.py
|
||||
# Description : Servo sweep
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/12
|
||||
########################################################################
|
||||
from gpiozero import AngularServo
|
||||
import time
|
||||
|
||||
myGPIO=18
|
||||
SERVO_DELAY_SEC = 0.001
|
||||
myCorrection=0.0
|
||||
maxPW=(2.5+myCorrection)/1000
|
||||
minPW=(0.5-myCorrection)/1000
|
||||
servo = AngularServo(myGPIO,initial_angle=0,min_angle=0, max_angle=180,min_pulse_width=minPW,max_pulse_width=maxPW)
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
for angle in range(0, 181, 1): # make servo rotate from 0 to 180 deg
|
||||
servo.angle = angle
|
||||
time.sleep(SERVO_DELAY_SEC)
|
||||
time.sleep(0.5)
|
||||
for angle in range(180, -1, -1): # make servo rotate from 180 to 0 deg
|
||||
servo.angle = angle
|
||||
time.sleep(SERVO_DELAY_SEC)
|
||||
time.sleep(0.5)
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : Sweep.py
|
||||
# Description : Servo sweep
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/12
|
||||
########################################################################
|
||||
import os
|
||||
os.system("sudo pigpiod")
|
||||
from gpiozero import AngularServo
|
||||
from gpiozero.pins.pigpio import PiGPIOFactory
|
||||
import time
|
||||
|
||||
my_factory = PiGPIOFactory()
|
||||
myGPIO=18
|
||||
SERVO_DELAY_SEC = 0.001
|
||||
myCorrection=0.0
|
||||
maxPW=(2.5+myCorrection)/1000
|
||||
minPW=(0.5-myCorrection)/1000
|
||||
servo = AngularServo(myGPIO,initial_angle=0,min_angle=0, max_angle=180,min_pulse_width=minPW,max_pulse_width=maxPW,pin_factory=my_factory)
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
for angle in range(0, 181, 1): # make servo rotate from 0 to 180 deg
|
||||
servo.angle = angle
|
||||
time.sleep(SERVO_DELAY_SEC)
|
||||
time.sleep(0.5)
|
||||
for angle in range(180, -1, -1): # make servo rotate from 180 to 0 deg
|
||||
servo.angle = angle
|
||||
time.sleep(SERVO_DELAY_SEC)
|
||||
time.sleep(0.5)
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
servo.close()
|
||||
os.system("sudo killall pigpiod")
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : SteppingMotor.py
|
||||
# Description : Drive SteppingMotor
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/12
|
||||
########################################################################
|
||||
from gpiozero import OutputDevice
|
||||
import time
|
||||
|
||||
motorPins = (18, 23, 24, 25) # define pins connected to four phase ABCD of stepper motor
|
||||
# motorPins = ("J8:12", "J8:16", "J8:18", "J8:22") # define pins connected to four phase ABCD of stepper motor
|
||||
motors = list(map(lambda pin: OutputDevice(pin), motorPins))
|
||||
CCWStep = (0x01,0x02,0x04,0x08) # define power supply order for rotating anticlockwise
|
||||
CWStep = (0x08,0x04,0x02,0x01) # define power supply order for rotating clockwise
|
||||
|
||||
# as for four phase stepping motor, four steps is a cycle. the function is used to drive the stepping motor clockwise or anticlockwise to take four steps
|
||||
def moveOnePeriod(direction,ms):
|
||||
for j in range(0,4,1): # cycle for power supply order
|
||||
for i in range(0,4,1): # assign to each pin
|
||||
if (direction == 1):# power supply order clockwise
|
||||
motors[i].on() if (CCWStep[j] == 1<<i) else motors[i].off()
|
||||
else : # power supply order anticlockwise
|
||||
motors[i].on() if CWStep[j] == 1<<i else motors[i].off()
|
||||
if(ms<3): # the delay can not be less than 3ms, otherwise it will exceed speed limit of the motor
|
||||
ms = 3
|
||||
time.sleep(ms*0.001)
|
||||
|
||||
# continuous rotation function, the parameter steps specifies the rotation cycles, every four steps is a cycle
|
||||
def moveSteps(direction, ms, steps):
|
||||
for i in range(steps):
|
||||
moveOnePeriod(direction, ms)
|
||||
|
||||
# function used to stop motor
|
||||
def motorStop():
|
||||
for i in range(0,4,1):
|
||||
motors.off()
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
moveSteps(0,3,512) # rotating 360 deg clockwise, a total of 2048 steps in a circle, 512 cycles
|
||||
time.sleep(0.5)
|
||||
moveSteps(1,3,512) # rotating 360 deg anticlockwise
|
||||
time.sleep(0.5)
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
print("Ending program")
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : SteppingMotor.py
|
||||
# Description : Drive SteppingMotor
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/12
|
||||
########################################################################
|
||||
import sys
|
||||
from time import sleep
|
||||
from gpiostepper import Stepper
|
||||
|
||||
#motorPins = ("J8:12", "J8:16", "J8:18", "J8:22") # define pins connected to four phase ABCD of stepper motor
|
||||
motorPins = (18, 23, 24, 25) # define pins connected to four phase ABCD of stepper motor
|
||||
number_of_steps = 32
|
||||
step_motor = Stepper(motorPins, number_of_steps = number_of_steps)
|
||||
speed = 600
|
||||
amount_of_gear_reduction = 64
|
||||
number_of_steps_per_revolution_geared_output = number_of_steps * amount_of_gear_reduction
|
||||
step_motor.set_speed(speed)
|
||||
def loop():
|
||||
while True:
|
||||
step_motor.step(number_of_steps_per_revolution_geared_output) # rotating 360 deg clockwise
|
||||
sleep(0.5)
|
||||
step_motor.step(-number_of_steps_per_revolution_geared_output)# rotating 360 deg anticlockwise
|
||||
sleep(0.5)
|
||||
|
||||
if __name__ == "__main__":
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
print("Ending program")
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
from gpiozero import OutputDevice
|
||||
from time import sleep
|
||||
|
||||
class Stepper:
|
||||
CW = -1
|
||||
CCW = 1
|
||||
"""Constructor"""
|
||||
def __init__(self, motor_pins, number_of_steps = 32, step_sequence = [[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]]):
|
||||
self.motor_pins = [OutputDevice(pin) for pin in motor_pins] # Control pins
|
||||
self.pin_count = len(motor_pins) # Number of control pins
|
||||
self.step_sequence = step_sequence # Sequence of control signals
|
||||
self.step_number = 0 # Which step the motor is on
|
||||
self.number_of_steps = number_of_steps # Total number of steps per internal motor revolution
|
||||
self.direction = self.CW # Rotation direction
|
||||
self.step_delay = 60 / self.number_of_steps / 240 # Rotation delay (240rpm == 7.81ms delay)
|
||||
|
||||
"""Sets speed in revolutions per minute"""
|
||||
def set_speed(self, what_speed):
|
||||
self.step_delay = 60 / self.number_of_steps / what_speed # Step delay in seconds
|
||||
print("Step Delay: {:.2f}ms".format(self.step_delay * 1000))
|
||||
"""Moves the motor steps_to_move steps. If the number is negative, the motor moves in the reverse direction."""
|
||||
def step(self, steps_to_move):
|
||||
# Determine how many steps to left to take
|
||||
steps_left = int(abs(steps_to_move))
|
||||
# Determine direction
|
||||
self.direction = self.CW if steps_to_move > 0 else self.CCW
|
||||
# Decrement the number of steps, moving one step each time
|
||||
while steps_left > 0:
|
||||
if self.direction == self.CCW:
|
||||
self.step_number = (self.step_number + 1) % self.number_of_steps
|
||||
else:
|
||||
self.step_number = (self.step_number - 1) % self.number_of_steps
|
||||
steps_left -= 1
|
||||
self.step_motor()
|
||||
|
||||
"""Moves the motor forward or backwards"""
|
||||
def step_motor(self):
|
||||
# Select the correct control signal sequence
|
||||
this_step = self.step_number % len(self.step_sequence)
|
||||
seq = self.step_sequence[this_step]
|
||||
# Set pin state accordingly
|
||||
for pin in range(self.pin_count):
|
||||
if seq[pin] == 1:
|
||||
self.motor_pins[pin].on()
|
||||
else:
|
||||
self.motor_pins[pin].off()
|
||||
sleep(self.step_delay)
|
||||
|
||||
"""Rotates the motor clockwise indefinitely"""
|
||||
def forward(self):
|
||||
for i in range(0,1024,1):
|
||||
self.step_number = (self.step_number - 1) % self.number_of_steps
|
||||
self.step_motor()
|
||||
|
||||
"""Rotates the motor counter-clockwise indefinitely"""
|
||||
def backward(self):
|
||||
for i in range(0,1024,1):
|
||||
self.step_number = (self.step_number + 1) % self.number_of_steps
|
||||
self.step_motor()
|
||||
"""Number of motor revolutions"""
|
||||
def movearound(self, step_around):
|
||||
if step_around >= 0:
|
||||
while step_around:
|
||||
self.step(32*64)
|
||||
step_around -= 1
|
||||
elif step_around < 0:
|
||||
while step_around:
|
||||
self.step(-32*64)
|
||||
step_around += 1
|
||||
"""Motor rotation Angle"""
|
||||
def moveangle(self, step_angle):
|
||||
self.step((step_angle*32*64)/360)
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
#############################################################################
|
||||
# Filename : LightWater02.py
|
||||
# Description : Control LED with 74HC595
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/12
|
||||
########################################################################
|
||||
from gpiozero import OutputDevice
|
||||
import time
|
||||
# Defines the data bit that is transmitted preferentially in the shiftOut function.
|
||||
LSBFIRST = 1
|
||||
MSBFIRST = 2
|
||||
# define the pins for 74HC595
|
||||
dataPin = OutputDevice(17) # DS Pin of 74HC595(Pin14)
|
||||
latchPin = OutputDevice(27) # ST_CP Pin of 74HC595(Pin12)
|
||||
clockPin = OutputDevice(22) # CH_CP Pin of 74HC595(Pin11)
|
||||
|
||||
# shiftOut function, use bit serial transmission.
|
||||
def shiftOut(order,val):
|
||||
for i in range(0,8):
|
||||
clockPin.off()
|
||||
if(order == LSBFIRST):
|
||||
dataPin.on() if (0x01&(val>>i)==0x01) else dataPin.off()
|
||||
elif(order == MSBFIRST):
|
||||
dataPin.on() if (0x80&(val<<i)==0x80) else dataPin.off()
|
||||
clockPin.on()
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
x=0x01
|
||||
for i in range(0,8):
|
||||
latchPin.off()# Output low level to latchPin
|
||||
shiftOut(LSBFIRST,x) # Send serial data to 74HC595
|
||||
latchPin.on() # Output high level to latchPin, and 74HC595 will update the data to the parallel output port.
|
||||
x<<=1 # make the variable move one bit to left once, then the bright LED move one step to the left once.
|
||||
time.sleep(0.1)
|
||||
x=0x80
|
||||
for i in range(0,8):
|
||||
latchPin.off()
|
||||
shiftOut(LSBFIRST,x)
|
||||
latchPin.on()
|
||||
x>>=1
|
||||
time.sleep(0.1)
|
||||
|
||||
def destroy():
|
||||
dataPin.close()
|
||||
latchPin.close()
|
||||
clockPin.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...' )
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
#############################################################################
|
||||
# Filename : SevenSegmentDisplay.py
|
||||
# Description : Control SevenSegmentDisplay with 74HC595
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/15
|
||||
########################################################################
|
||||
from gpiozero import OutputDevice
|
||||
import time
|
||||
|
||||
LSBFIRST = 1
|
||||
MSBFIRST = 2
|
||||
# define the pins for 74HC595
|
||||
dataPin = OutputDevice(17) # DS Pin of 74HC595(Pin14)
|
||||
latchPin = OutputDevice(27) # ST_CP Pin of 74HC595(Pin12)
|
||||
clockPin = OutputDevice(22) # CH_CP Pin of 74HC595(Pin11)
|
||||
# SevenSegmentDisplay display the character "0"- "F" successively
|
||||
num = [0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e]
|
||||
|
||||
def shiftOut(order,val):
|
||||
for i in range(0,8):
|
||||
clockPin.off()
|
||||
if(order == LSBFIRST):
|
||||
dataPin.on() if (0x01&(val>>i)==0x01) else dataPin.off()
|
||||
elif(order == MSBFIRST):
|
||||
dataPin.on() if (0x80&(val<<i)==0x80) else dataPin.off()
|
||||
clockPin.on()
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
for i in range(0,len(num)):
|
||||
latchPin.off()
|
||||
shiftOut(MSBFIRST,num[i]) # Send serial data to 74HC595
|
||||
latchPin.on()
|
||||
time.sleep(0.5)
|
||||
for i in range(0,len(num)):
|
||||
latchPin.off()
|
||||
shiftOut(MSBFIRST,num[i]&0x7f) # Use "&0x7f" to display the decimal point.
|
||||
latchPin.on()
|
||||
time.sleep(0.5)
|
||||
|
||||
def destroy():
|
||||
dataPin.close()
|
||||
latchPin.close()
|
||||
clockPin.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...' )
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env python3
|
||||
#############################################################################
|
||||
# Filename : StopWatch.py
|
||||
# Description : Control 4_Digit_7_Segment_Display with 74HC595
|
||||
# Author : www.freenove.com
|
||||
# modification: 2023/05/15
|
||||
########################################################################
|
||||
from gpiozero import OutputDevice
|
||||
import time
|
||||
import threading
|
||||
|
||||
LSBFIRST = 1
|
||||
MSBFIRST = 2
|
||||
# define the pins connect to 74HC595
|
||||
dataPin = OutputDevice(24) # DS Pin of 74HC595
|
||||
latchPin = OutputDevice(23) # ST_CP Pin of 74HC595
|
||||
clockPin = OutputDevice(18) # SH_CP Pin of 74HC595
|
||||
num = (0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90)
|
||||
digitPin = (17,27,22,10) # Define the pin of 7-segment display common end
|
||||
outputs = list(map(lambda pin: OutputDevice(pin), digitPin))
|
||||
counter = 0 # Variable counter, the number will be dislayed by 7-segment display
|
||||
t = 0 # define the Timer object
|
||||
|
||||
def shiftOut(order,val):
|
||||
for i in range(0,8):
|
||||
clockPin.off()
|
||||
if(order == LSBFIRST):
|
||||
dataPin.on() if (0x01&(val>>i)==0x01) else dataPin.off()
|
||||
elif(order == MSBFIRST):
|
||||
dataPin.on() if (0x80&(val<<i)==0x80) else dataPin.off()
|
||||
clockPin.on()
|
||||
|
||||
def outData(data): # function used to output data for 74HC595
|
||||
latchPin.off()
|
||||
shiftOut(MSBFIRST,data)
|
||||
latchPin.on()
|
||||
|
||||
def selectDigit(digit): # Open one of the 7-segment display and close the remaining three, the parameter digit is optional for 1,2,4,8
|
||||
outputs[0].off() if ((digit&0x08) == 0x08) else outputs[0].on()
|
||||
outputs[1].off() if ((digit&0x04) == 0x04) else outputs[1].on()
|
||||
outputs[2].off() if ((digit&0x02) == 0x02) else outputs[2].on()
|
||||
outputs[3].off() if ((digit&0x01) == 0x01) else outputs[3].on()
|
||||
|
||||
def display(dec): # display function for 7-segment display
|
||||
outData(0xff) # eliminate residual display
|
||||
selectDigit(0x01) # Select the first, and display the single digit
|
||||
outData(num[dec%10])
|
||||
time.sleep(0.003) # display duration
|
||||
outData(0xff)
|
||||
selectDigit(0x02) # Select the second, and display the tens digit
|
||||
outData(num[dec%100//10])
|
||||
time.sleep(0.003)
|
||||
outData(0xff)
|
||||
selectDigit(0x04) # Select the third, and display the hundreds digit
|
||||
outData(num[dec%1000//100])
|
||||
time.sleep(0.003)
|
||||
outData(0xff)
|
||||
selectDigit(0x08) # Select the fourth, and display the thousands digit
|
||||
outData(num[dec%10000//1000])
|
||||
time.sleep(0.003)
|
||||
def timer():
|
||||
global counter
|
||||
global t
|
||||
t = threading.Timer(1.0,timer) # reset time of timer to 1s
|
||||
t.start() # Start timing
|
||||
counter+=1
|
||||
print ("counter : %d"%counter)
|
||||
|
||||
def loop():
|
||||
global t
|
||||
global counter
|
||||
t = threading.Timer(1.0,timer) # set the timer
|
||||
t.start() # Start timing
|
||||
while True:
|
||||
display(counter) # display the number counter
|
||||
|
||||
def destroy():
|
||||
global t
|
||||
dataPin.close()
|
||||
latchPin.close()
|
||||
clockPin.close()
|
||||
t.cancel()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...' )
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python3
|
||||
#############################################################################
|
||||
# Filename : LEDMatrix.py
|
||||
# Description : Control LEDMatrix with 74HC595
|
||||
# auther : www.freenove.com
|
||||
# modification: 2023/05/15
|
||||
########################################################################
|
||||
from gpiozero import OutputDevice
|
||||
import time
|
||||
|
||||
LSBFIRST = 1
|
||||
MSBFIRST = 2
|
||||
# define the pins connect to 74HC595
|
||||
dataPin = OutputDevice(17) # DS Pin of 74HC595(Pin14)
|
||||
latchPin = OutputDevice(27) # ST_CP Pin of 74HC595(Pin12)
|
||||
clockPin = OutputDevice(22) # CH_CP Pin of 74HC595(Pin11)
|
||||
pic = [0x1c,0x22,0x51,0x45,0x45,0x51,0x22,0x1c] # data of smiling face
|
||||
data = [ # data of "0-F"
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # " "
|
||||
0x00, 0x00, 0x3E, 0x41, 0x41, 0x3E, 0x00, 0x00, # "0"
|
||||
0x00, 0x00, 0x21, 0x7F, 0x01, 0x00, 0x00, 0x00, # "1"
|
||||
0x00, 0x00, 0x23, 0x45, 0x49, 0x31, 0x00, 0x00, # "2"
|
||||
0x00, 0x00, 0x22, 0x49, 0x49, 0x36, 0x00, 0x00, # "3"
|
||||
0x00, 0x00, 0x0E, 0x32, 0x7F, 0x02, 0x00, 0x00, # "4"
|
||||
0x00, 0x00, 0x79, 0x49, 0x49, 0x46, 0x00, 0x00, # "5"
|
||||
0x00, 0x00, 0x3E, 0x49, 0x49, 0x26, 0x00, 0x00, # "6"
|
||||
0x00, 0x00, 0x60, 0x47, 0x48, 0x70, 0x00, 0x00, # "7"
|
||||
0x00, 0x00, 0x36, 0x49, 0x49, 0x36, 0x00, 0x00, # "8"
|
||||
0x00, 0x00, 0x32, 0x49, 0x49, 0x3E, 0x00, 0x00, # "9"
|
||||
0x00, 0x00, 0x3F, 0x44, 0x44, 0x3F, 0x00, 0x00, # "A"
|
||||
0x00, 0x00, 0x7F, 0x49, 0x49, 0x36, 0x00, 0x00, # "B"
|
||||
0x00, 0x00, 0x3E, 0x41, 0x41, 0x22, 0x00, 0x00, # "C"
|
||||
0x00, 0x00, 0x7F, 0x41, 0x41, 0x3E, 0x00, 0x00, # "D"
|
||||
0x00, 0x00, 0x7F, 0x49, 0x49, 0x41, 0x00, 0x00, # "E"
|
||||
0x00, 0x00, 0x7F, 0x48, 0x48, 0x40, 0x00, 0x00, # "F"
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # " "
|
||||
]
|
||||
|
||||
def shiftOut(order,val):
|
||||
for i in range(0,8):
|
||||
clockPin.off()
|
||||
if(order == LSBFIRST):
|
||||
dataPin.on() if (0x01&(val>>i)==0x01) else dataPin.off()
|
||||
elif(order == MSBFIRST):
|
||||
dataPin.on() if (0x80&(val<<i)==0x80) else dataPin.off()
|
||||
clockPin.on()
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
for j in range(0,500): # Repeat enough times to display the smiling face a period of time
|
||||
x=0x80
|
||||
for i in range(0,8):
|
||||
latchPin.off()
|
||||
shiftOut(MSBFIRST,pic[i]) #first shift data of line information to first stage 74HC959
|
||||
|
||||
shiftOut(MSBFIRST,~x) #then shift data of column information to second stage 74HC959
|
||||
latchPin.on() # Output data of two stage 74HC595 at the same time
|
||||
time.sleep(0.001) # display the next column
|
||||
x>>=1
|
||||
for k in range(0,len(data)-8): #len(data) total number of "0-F" columns
|
||||
for j in range(0,20): # times of repeated displaying LEDMatrix in every frame, the bigger the "j", the longer the display time.
|
||||
x=0x80 # Set the column information to start from the first column
|
||||
for i in range(k,k+8):
|
||||
latchPin.off()
|
||||
shiftOut(MSBFIRST,data[i])
|
||||
shiftOut(MSBFIRST,~x)
|
||||
latchPin.on()
|
||||
time.sleep(0.001)
|
||||
x>>=1
|
||||
def destroy():
|
||||
dataPin.close()
|
||||
latchPin.close()
|
||||
clockPin.close()
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...' )
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : I2CLCD1602.py
|
||||
# Description : Use the LCD display data
|
||||
# Author : freenove
|
||||
# modification: 2023/05/15
|
||||
########################################################################
|
||||
import smbus
|
||||
from time import sleep, strftime
|
||||
from datetime import datetime
|
||||
from LCD1602 import CharLCD1602
|
||||
|
||||
lcd1602 = CharLCD1602()
|
||||
def get_cpu_temp(): # get CPU temperature from file "/sys/class/thermal/thermal_zone0/temp"
|
||||
tmp = open('/sys/class/thermal/thermal_zone0/temp')
|
||||
cpu = tmp.read()
|
||||
tmp.close()
|
||||
return '{:.2f}'.format( float(cpu)/1000 ) + ' C '
|
||||
|
||||
def get_time_now(): # get system time
|
||||
return datetime.now().strftime(' %H:%M:%S')
|
||||
|
||||
def loop():
|
||||
lcd1602.init_lcd()
|
||||
count = 0
|
||||
while(True):
|
||||
lcd1602.clear()
|
||||
lcd1602.write(0, 0, 'CPU: ' + get_cpu_temp() )# display CPU temperature
|
||||
lcd1602.write(0, 1, get_time_now() ) # display the time
|
||||
sleep(1)
|
||||
def destroy():
|
||||
lcd1602.clear()
|
||||
if __name__ == '__main__':
|
||||
print ('Program is starting ... ')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt:
|
||||
destroy()
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env python3
|
||||
import time
|
||||
import smbus
|
||||
import subprocess
|
||||
|
||||
class CharLCD1602(object):
|
||||
def __init__(self):
|
||||
# Note you need to change the bus number to 0 if running on a revision 1 Raspberry Pi.
|
||||
self.bus = smbus.SMBus(1)
|
||||
self.BLEN = 1 # turn on/off background light
|
||||
self.PCF8574_address = 0x27 # I2C address of the PCF8574 chip.
|
||||
self.PCF8574A_address = 0x3f # I2C address of the PCF8574A chip.
|
||||
self.LCD_ADDR =self.PCF8574_address
|
||||
def write_word(self,addr, data):
|
||||
temp = data
|
||||
if self.BLEN == 1:
|
||||
temp |= 0x08
|
||||
else:
|
||||
temp &= 0xF7
|
||||
self.bus.write_byte(addr ,temp)
|
||||
|
||||
def send_command(self,comm):
|
||||
# Send bit7-4 firstly
|
||||
buf = comm & 0xF0
|
||||
buf |= 0x04 # RS = 0, RW = 0, EN = 1
|
||||
self.write_word(self.LCD_ADDR ,buf)
|
||||
time.sleep(0.002)
|
||||
buf &= 0xFB # Make EN = 0
|
||||
self.write_word(self.LCD_ADDR ,buf)
|
||||
# Send bit3-0 secondly
|
||||
buf = (comm & 0x0F) << 4
|
||||
buf |= 0x04 # RS = 0, RW = 0, EN = 1
|
||||
self.write_word(self.LCD_ADDR ,buf)
|
||||
time.sleep(0.002)
|
||||
buf &= 0xFB # Make EN = 0
|
||||
self.write_word(self.LCD_ADDR ,buf)
|
||||
|
||||
def send_data(self,data):
|
||||
# Send bit7-4 firstly
|
||||
buf = data & 0xF0
|
||||
buf |= 0x05 # RS = 1, RW = 0, EN = 1
|
||||
self.write_word(self.LCD_ADDR ,buf)
|
||||
time.sleep(0.002)
|
||||
buf &= 0xFB # Make EN = 0
|
||||
self.write_word(self.LCD_ADDR ,buf)
|
||||
# Send bit3-0 secondly
|
||||
buf = (data & 0x0F) << 4
|
||||
buf |= 0x05 # RS = 1, RW = 0, EN = 1
|
||||
self.write_word(self.LCD_ADDR ,buf)
|
||||
time.sleep(0.002)
|
||||
buf &= 0xFB # Make EN = 0
|
||||
self.write_word(self.LCD_ADDR ,buf)
|
||||
|
||||
def i2c_scan(self):
|
||||
cmd = "i2cdetect -y 1 |awk \'NR>1 {$1=\"\";print}\'"
|
||||
result = subprocess.check_output(cmd, shell=True).decode()
|
||||
result = result.replace("\n", "").replace(" --", "")
|
||||
i2c_list = result.split(' ')
|
||||
return i2c_list
|
||||
|
||||
def init_lcd(self,addr=None, bl=1):
|
||||
i2c_list = self.i2c_scan()
|
||||
# print(f"i2c_list: {i2c_list}")
|
||||
if addr is None:
|
||||
if '27' in i2c_list:
|
||||
self.LCD_ADDR = self.PCF8574_address
|
||||
elif '3f' in i2c_list:
|
||||
self.LCD_ADDR = self.PCF8574A_address
|
||||
else:
|
||||
raise IOError("I2C address 0x27 or 0x3f no found.")
|
||||
else:
|
||||
self.LCD_ADDR = addr
|
||||
if str(hex(addr)).strip('0x') not in i2c_list:
|
||||
raise IOError(f"I2C address {str(hex(addr))} or 0x3f no found.")
|
||||
self.BLEN = bl
|
||||
try:
|
||||
self.send_command(0x33) # Must initialize to 8-line mode at first
|
||||
time.sleep(0.005)
|
||||
self.send_command(0x32) # Then initialize to 4-line mode
|
||||
time.sleep(0.005)
|
||||
self.send_command(0x28) # 2 Lines & 5*7 dots
|
||||
time.sleep(0.005)
|
||||
self.send_command(0x0C) # Enable display without cursor
|
||||
time.sleep(0.005)
|
||||
self.send_command(0x01) # Clear Screen
|
||||
self.buswrite_byte(self.LCD_ADDR, 0x08)
|
||||
except:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def clear(self):
|
||||
self.send_command(0x01) # Clear Screen
|
||||
|
||||
def openlight(self): # Enable the backlight
|
||||
self.bus.write_byte(0x27,0x08)
|
||||
self.bus.close()
|
||||
|
||||
def write(self,x, y, str):
|
||||
if x < 0:
|
||||
x = 0
|
||||
if x > 15:
|
||||
x = 15
|
||||
if y <0:
|
||||
y = 0
|
||||
if y > 1:
|
||||
y = 1
|
||||
# Move cursor
|
||||
addr = 0x80 + 0x40 * y + x
|
||||
self.send_command(addr)
|
||||
for chr in str:
|
||||
self.send_data(ord(chr))
|
||||
def display_num(self,x, y, num):
|
||||
addr = 0x80 + 0x40 * y + x
|
||||
self.send_command(addr)
|
||||
self.send_data(num)
|
||||
|
||||
def loop():
|
||||
count = 0
|
||||
while(True):
|
||||
lcd1602.clear()
|
||||
lcd1602.write(0, 0, ' Hello World! ' )# display CPU temperature
|
||||
lcd1602.write(0, 1, ' Counter: ' + str(count) ) # display the time
|
||||
time.sleep(1)
|
||||
count += 1
|
||||
def destroy():
|
||||
lcd1602.clear()
|
||||
lcd1602 = CharLCD1602()
|
||||
if __name__ == '__main__':
|
||||
print ('Program is starting ... ')
|
||||
lcd1602.init_lcd(addr=None, bl=1)
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt:
|
||||
destroy()
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
#############################################################################
|
||||
# Filename : DHT11.py
|
||||
# Description : read the temperature and humidity data of DHT11
|
||||
# Author : freenove
|
||||
# modification: 2020/10/16
|
||||
########################################################################
|
||||
import RPi.GPIO as GPIO
|
||||
import time
|
||||
import Freenove_DHT as DHT
|
||||
DHTPin = 11 #define the pin of DHT11
|
||||
|
||||
def loop():
|
||||
dht = DHT.DHT(DHTPin) #create a DHT class object
|
||||
counts = 0 # Measurement counts
|
||||
while(True):
|
||||
counts += 1
|
||||
print("Measurement counts: ", counts)
|
||||
for i in range(0,15):
|
||||
chk = dht.readDHT11() #read DHT11 and get a return value. Then determine whether data read is normal according to the return value.
|
||||
if (chk is dht.DHTLIB_OK): #read DHT11 and get a return value. Then determine whether data read is normal according to the return value.
|
||||
print("DHT11,OK!")
|
||||
break
|
||||
time.sleep(0.1)
|
||||
print("Humidity : %.2f, \t Temperature : %.2f \n"%(dht.humidity,dht.temperature))
|
||||
time.sleep(2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
print ('Program is starting ... ')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt:
|
||||
GPIO.cleanup()
|
||||
exit()
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env python3
|
||||
#############################################################################
|
||||
# Filename : Freenove_DHT.py
|
||||
# Description : DHT Temperature & Humidity Sensor library for Raspberry
|
||||
# Author : freenove
|
||||
# modification: 2020/10/16
|
||||
########################################################################
|
||||
import RPi.GPIO as GPIO
|
||||
import time
|
||||
|
||||
class DHT(object):
|
||||
DHTLIB_OK = 0
|
||||
DHTLIB_ERROR_CHECKSUM = -1
|
||||
DHTLIB_ERROR_TIMEOUT = -2
|
||||
DHTLIB_INVALID_VALUE = -999
|
||||
|
||||
DHTLIB_DHT11_WAKEUP = 0.020#0.018 #18ms
|
||||
DHTLIB_TIMEOUT = 0.0001 #100us
|
||||
|
||||
humidity = 0
|
||||
temperature = 0
|
||||
|
||||
def __init__(self,pin):
|
||||
self.pin = pin
|
||||
self.bits = [0,0,0,0,0]
|
||||
GPIO.setmode(GPIO.BOARD)
|
||||
#Read DHT sensor, store the original data in bits[]
|
||||
def readSensor(self,pin,wakeupDelay):
|
||||
mask = 0x80
|
||||
idx = 0
|
||||
self.bits = [0,0,0,0,0]
|
||||
# Clear sda
|
||||
GPIO.setup(pin,GPIO.OUT)
|
||||
GPIO.output(pin,GPIO.HIGH)
|
||||
time.sleep(0.5)
|
||||
# start signal
|
||||
GPIO.output(pin,GPIO.LOW)
|
||||
time.sleep(wakeupDelay)
|
||||
GPIO.output(pin,GPIO.HIGH)
|
||||
# time.sleep(0.000001)
|
||||
GPIO.setup(pin,GPIO.IN)
|
||||
|
||||
loopCnt = self.DHTLIB_TIMEOUT
|
||||
# Waiting echo
|
||||
t = time.time()
|
||||
while True:
|
||||
if (GPIO.input(pin) == GPIO.LOW):
|
||||
break
|
||||
if((time.time() - t) > loopCnt):
|
||||
return self.DHTLIB_ERROR_TIMEOUT
|
||||
# Waiting echo low level end
|
||||
t = time.time()
|
||||
while(GPIO.input(pin) == GPIO.LOW):
|
||||
if((time.time() - t) > loopCnt):
|
||||
#print ("Echo LOW")
|
||||
return self.DHTLIB_ERROR_TIMEOUT
|
||||
# Waiting echo high level end
|
||||
t = time.time()
|
||||
while(GPIO.input(pin) == GPIO.HIGH):
|
||||
if((time.time() - t) > loopCnt):
|
||||
#print ("Echo HIGH")
|
||||
return self.DHTLIB_ERROR_TIMEOUT
|
||||
for i in range(0,40,1):
|
||||
t = time.time()
|
||||
while(GPIO.input(pin) == GPIO.LOW):
|
||||
if((time.time() - t) > loopCnt):
|
||||
#print ("Data Low %d"%(i))
|
||||
return self.DHTLIB_ERROR_TIMEOUT
|
||||
t = time.time()
|
||||
while(GPIO.input(pin) == GPIO.HIGH):
|
||||
if((time.time() - t) > loopCnt):
|
||||
#print ("Data HIGH %d"%(i))
|
||||
return self.DHTLIB_ERROR_TIMEOUT
|
||||
if((time.time() - t) > 0.00005):
|
||||
self.bits[idx] |= mask
|
||||
#print("t : %f"%(time.time()-t))
|
||||
mask >>= 1
|
||||
if(mask == 0):
|
||||
mask = 0x80
|
||||
idx += 1
|
||||
#print (self.bits)
|
||||
GPIO.setup(pin,GPIO.OUT)
|
||||
GPIO.output(pin,GPIO.HIGH)
|
||||
return self.DHTLIB_OK
|
||||
#Read DHT sensor, analyze the data of temperature and humidity
|
||||
def readDHT11Once(self):
|
||||
rv = self.readSensor(self.pin,self.DHTLIB_DHT11_WAKEUP)
|
||||
if (rv is not self.DHTLIB_OK):
|
||||
self.humidity = self.DHTLIB_INVALID_VALUE
|
||||
self.temperature = self.DHTLIB_INVALID_VALUE
|
||||
return rv
|
||||
self.humidity = self.bits[0]
|
||||
self.temperature = self.bits[2] + self.bits[3]*0.1
|
||||
sumChk = ((self.bits[0] + self.bits[1] + self.bits[2] + self.bits[3]) & 0xFF)
|
||||
if(self.bits[4] is not sumChk):
|
||||
return self.DHTLIB_ERROR_CHECKSUM
|
||||
return self.DHTLIB_OK
|
||||
def readDHT11(self):
|
||||
result = self.DHTLIB_INVALID_VALUE
|
||||
for i in range(0,15):
|
||||
result = self.readDHT11Once()
|
||||
if result == self.DHTLIB_OK:
|
||||
return self.DHTLIB_OK
|
||||
time.sleep(0.1)
|
||||
return result
|
||||
|
||||
|
||||
def loop():
|
||||
dht = DHT(11)
|
||||
sumCnt = 0
|
||||
okCnt = 0
|
||||
while(True):
|
||||
sumCnt += 1
|
||||
chk = dht.readDHT11()
|
||||
if (chk is 0):
|
||||
okCnt += 1
|
||||
okRate = 100.0*okCnt/sumCnt;
|
||||
print("sumCnt : %d, \t okRate : %.2f%% "%(sumCnt,okRate))
|
||||
print("chk : %d, \t Humidity : %.2f, \t Temperature : %.2f "%(chk,dht.humidity,dht.temperature))
|
||||
time.sleep(3)
|
||||
|
||||
if __name__ == '__main__':
|
||||
print ('Program is starting ... ')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
exit()
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
from setuptools import setup,find_packages
|
||||
|
||||
setup(
|
||||
name = "Freenove_DHT",
|
||||
version = "V1.0.1",
|
||||
description = "Read DHT Sensor",
|
||||
author = "Freenove",
|
||||
url = "http://www.freenove.com",
|
||||
license = " ",
|
||||
packages = find_packages(),
|
||||
scripts = ["Freenove_DHT.py"],
|
||||
)
|
||||
@@ -0,0 +1,203 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : Keypad.py
|
||||
# Description : The module of matrix keypad
|
||||
# Author : freenove
|
||||
# modification: 2023/05/15
|
||||
########################################################################
|
||||
from gpiozero import InputDevice, OutputDevice
|
||||
import time
|
||||
#class Key:Define some of the properties of Key
|
||||
class Key(object):
|
||||
NO_KEY = '\0'
|
||||
#Defines the four states of Key
|
||||
IDLE = 0
|
||||
PRESSED = 1
|
||||
HOLD = 2
|
||||
RELEASED = 3
|
||||
#define OPEN and CLOSED
|
||||
OPEN = 0
|
||||
CLOSED =1
|
||||
#constructor
|
||||
def __init__(self):
|
||||
self.kchar = self.NO_KEY
|
||||
self.kstate = self.IDLE
|
||||
self.kcode = -1
|
||||
self.stateChanged = False
|
||||
|
||||
class Keypad(object):
|
||||
NULL = '\0'
|
||||
LIST_MAX = 10 #Max number of keys on the active list.
|
||||
MAPSIZE = 10 #MAPSIZE is the number of rows (times 16 columns)
|
||||
bitMap = [0]*MAPSIZE
|
||||
key = [Key()]*LIST_MAX
|
||||
holdTime = 500 #key hold time
|
||||
holdTimer = 0
|
||||
startTime = 0
|
||||
#Allows custom keymap, pin configuration, and keypad sizes.
|
||||
def __init__(self,usrKeyMap,row_Pins,col_Pins,num_Rows,num_Cols):
|
||||
self.rowPins = row_Pins
|
||||
self.colPins = col_Pins
|
||||
self.numRows = num_Rows
|
||||
self.numCols = num_Cols
|
||||
|
||||
self.keymap = usrKeyMap
|
||||
self.setDebounceTime(10)
|
||||
#Returns a single key only. Retained for backwards compatibility.
|
||||
def getKey(self):
|
||||
single_key = True
|
||||
if(self.getKeys() and self.key[0].stateChanged and (self.key[0].kstate == self.key[0].PRESSED)):
|
||||
return self.key[0].kchar
|
||||
single_key = False
|
||||
return self.key[0].NO_KEY
|
||||
#Populate the key list.
|
||||
def getKeys(self):
|
||||
keyActivity = False
|
||||
#Limit how often the keypad is scanned.
|
||||
if((time.time() - self.startTime) > self.debounceTime*0.001):
|
||||
self.scanKeys()
|
||||
keyActivity = self.updateList()
|
||||
self.startTime = time.time()
|
||||
return keyActivity
|
||||
#Hardware scan ,the result store in bitMap
|
||||
def scanKeys(self):
|
||||
#Re-intialize the row pins. Allows sharing these pins with other hardware.
|
||||
inputs = list(map(lambda pin: InputDevice(pin, pull_up=True), self.rowPins))
|
||||
#bitMap stores ALL the keys that are being pressed. outputs = OutputDevice(pin_c,active_high=False)
|
||||
for pin_c in self.colPins:
|
||||
outputs = OutputDevice(pin_c)
|
||||
outputs.off()
|
||||
i=0
|
||||
for r in self.rowPins: #keypress is active low so invert to high. inputs[i].is_active inputs[i].value
|
||||
self.bitMap[self.rowPins.index(r)] = self.bitWrite(self.bitMap[self.rowPins.index(r)],self.colPins.index(pin_c), inputs[i].value)
|
||||
i =i+1
|
||||
#Set pin to high impedance input. Effectively ends column pulse.
|
||||
outputs.on()
|
||||
outputs.close()
|
||||
outputs = InputDevice(pin_c,pull_up=True)
|
||||
#Manage the list without rearranging the keys. Returns true if any keys on the list changed state.
|
||||
def updateList(self):
|
||||
anyActivity = False
|
||||
kk = Key()
|
||||
#Delete any IDLE keys
|
||||
for i in range(self.LIST_MAX):
|
||||
if(self.key[i].kstate == kk.IDLE):
|
||||
self.key[i].kchar = kk.NO_KEY
|
||||
self.key[i].kcode = -1
|
||||
self.key[i].stateChanged = False
|
||||
# Add new keys to empty slots in the key list.
|
||||
for r in range(self.numRows):
|
||||
for c in range(self.numCols):
|
||||
button = self.bitRead(self.bitMap[r],c)
|
||||
keyChar = self.keymap[r * self.numCols +c]
|
||||
keyCode = r * self.numCols +c
|
||||
idx = self.findInList(keyCode)
|
||||
#Key is already on the list so set its next state.
|
||||
if(idx > -1):
|
||||
self.nextKeyState(idx,button)
|
||||
#Key is NOT on the list so add it.
|
||||
if((idx == -1) and button):
|
||||
for i in range(self.LIST_MAX):
|
||||
if(self.key[i].kchar == kk.NO_KEY): #Find an empty slot or don't add key to list.
|
||||
self.key[i].kchar = keyChar
|
||||
self.key[i].kcode = keyCode
|
||||
self.key[i].kstate = kk.IDLE #Keys NOT on the list have an initial state of IDLE.
|
||||
self.nextKeyState(i,button)
|
||||
break #Don't fill all the empty slots with the same key.
|
||||
#Report if the user changed the state of any key.
|
||||
for i in range(self.LIST_MAX):
|
||||
if(self.key[i].stateChanged):
|
||||
anyActivity = True
|
||||
return anyActivity
|
||||
#This function is a state machine but is also used for debouncing the keys.
|
||||
def nextKeyState(self,idx, button):
|
||||
self.key[idx].stateChanged = False
|
||||
kk = Key()
|
||||
if(self.key[idx].kstate == kk.IDLE):
|
||||
if(button == kk.CLOSED):
|
||||
self.transitionTo(idx,kk.PRESSED)
|
||||
self.holdTimer = time.time() #Get ready for next HOLD state.
|
||||
elif(self.key[idx].kstate == kk.PRESSED):
|
||||
if((time.time() - self.holdTimer) > self.holdTime*0.001): #Waiting for a key HOLD...
|
||||
self.transitionTo(idx,kk.HOLD)
|
||||
elif(button == kk.OPEN): # or for a key to be RELEASED.
|
||||
self.transitionTo(idx,kk.RELEASED)
|
||||
elif(self.key[idx].kstate == kk.HOLD):
|
||||
if(button == kk.OPEN):
|
||||
self.transitionTo(idx,kk.RELEASED)
|
||||
elif(self.key[idx].kstate == kk.RELEASED):
|
||||
self.transitionTo(idx,kk.IDLE)
|
||||
|
||||
def transitionTo(self,idx,nextState):
|
||||
self.key[idx].kstate = nextState
|
||||
self.key[idx].stateChanged = True
|
||||
#Search by code for a key in the list of active keys.
|
||||
#Returns -1 if not found or the index into the list of active keys.
|
||||
def findInList(self,keyCode):
|
||||
for i in range(self.LIST_MAX):
|
||||
if(self.key[i].kcode == keyCode):
|
||||
return i
|
||||
return -1
|
||||
#set Debounce Time, The default is 50ms
|
||||
def setDebounceTime(self,ms):
|
||||
self.debounceTime = ms
|
||||
#set HoldTime,The default is 500ms
|
||||
def setHoldTime(self,ms):
|
||||
self.holdTime = ms
|
||||
#
|
||||
def isPressed(keyChar):
|
||||
for i in range(self.LIST_MAX):
|
||||
if(self.key[i].kchar == keyChar):
|
||||
if(self.key[i].kstate == self.self.key[i].PRESSED and self.key[i].stateChanged):
|
||||
return True
|
||||
return False
|
||||
#
|
||||
def waitForKey():
|
||||
kk = Key()
|
||||
waitKey = kk.NO_KEY
|
||||
while(waitKey == kk.NO_KEY):
|
||||
waitKey = getKey()
|
||||
return waitKey
|
||||
|
||||
def getState():
|
||||
return self.key[0].kstate
|
||||
#
|
||||
def keyStateChanged():
|
||||
return self.key[0].stateChanged
|
||||
|
||||
def bitWrite(self,x,n,b):
|
||||
if(b):
|
||||
x |= (1<<n)
|
||||
else:
|
||||
x &=(~(1<<n))
|
||||
return x
|
||||
def bitRead(self,x,n):
|
||||
if((x>>n)&1 == 1):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
#######################EXAMPLE##################################
|
||||
ROWS = 4
|
||||
COLS = 4
|
||||
keys = [ '1','2','3','A',
|
||||
'4','5','6','B',
|
||||
'7','8','9','C',
|
||||
'*','0','#','D' ]
|
||||
rowsPins = [18, 23, 24, 25]
|
||||
colsPins = [10, 22, 27, 17]
|
||||
|
||||
def loop():
|
||||
keypad = Keypad(keys,rowsPins,colsPins,ROWS,COLS)
|
||||
keypad.setDebounceTime(50)
|
||||
while(True):
|
||||
key = keypad.getKey()
|
||||
if(key != keypad.NULL):
|
||||
print ("You Pressed Key : %c "%(key) )
|
||||
|
||||
if __name__ == '__main__': # Program start from here
|
||||
print ("Program is starting ... ")
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the child program destroy() will be executed.
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,38 @@
|
||||
import time
|
||||
from gpiozero import InputDevice, OutputDevice
|
||||
|
||||
output_pins = [10, 22, 27, 17]
|
||||
input_pins = [18, 23, 24, 25]
|
||||
|
||||
inputs = list(map(lambda pin: InputDevice(pin, pull_up=True), input_pins))
|
||||
outputs = list(map(lambda pin: InputDevice(pin, pull_up=True), output_pins))
|
||||
|
||||
mapping = [
|
||||
['1', '2', '3', 'A'],
|
||||
['4', '5', '6', 'B'],
|
||||
['7', '8', '9', 'C'],
|
||||
['*', '0', '#', 'D'],
|
||||
]
|
||||
|
||||
pressed = set([])
|
||||
|
||||
while True:
|
||||
for o in range(4):
|
||||
outputs[o].close()
|
||||
tmp = OutputDevice(output_pins[o], active_high=False)
|
||||
tmp.on()
|
||||
for i in range(4):
|
||||
key = mapping[i][o]
|
||||
if inputs[i].is_active:
|
||||
if key == '':
|
||||
continue
|
||||
if key not in pressed:
|
||||
print(key)
|
||||
pressed.add(key)
|
||||
else:
|
||||
if key in pressed:
|
||||
pressed.remove(key)
|
||||
|
||||
tmp.close()
|
||||
outputs[o] = InputDevice(output_pins[o], pull_up=True)
|
||||
time.sleep(0.02)
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : MatrixKeypad.py
|
||||
# Description : obtain the key code of 4x4 Matrix Keypad
|
||||
# Author : freenove
|
||||
# modification: 2023/05/15
|
||||
########################################################################
|
||||
import Keypad #import module Keypad
|
||||
ROWS = 4 # number of rows of the Keypad
|
||||
COLS = 4 #number of columns of the Keypad
|
||||
keys = [ '1','2','3','A', #key code
|
||||
'4','5','6','B',
|
||||
'7','8','9','C',
|
||||
'*','0','#','D' ]
|
||||
rowsPins = [18, 23, 24, 25] #connect to the row pinouts of the keypad
|
||||
colsPins = [10, 22, 27, 17] #connect to the column pinouts of the keypad
|
||||
def loop():
|
||||
keypad = Keypad.Keypad(keys,rowsPins,colsPins,ROWS,COLS) #creat Keypad object
|
||||
keypad.setDebounceTime(50) #set the debounce time
|
||||
while(True):
|
||||
key = keypad.getKey() #obtain the state of keys
|
||||
if(key != keypad.NULL): #if there is key pressed, print its key code.
|
||||
print ("You Pressed Key : %c "%(key))
|
||||
|
||||
if __name__ == '__main__': #Program start from here
|
||||
print ("Program is starting ... ")
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: #When 'Ctrl+C' is pressed, exit the program.
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : SenseLED.py
|
||||
# Description : Control led with infrared Motion sensor.
|
||||
# auther : www.freenove.com
|
||||
# modification: 2023/05/11
|
||||
########################################################################
|
||||
from gpiozero import LED,MotionSensor
|
||||
import time
|
||||
|
||||
ledPin = 18 # define ledPin
|
||||
sensorPin = 17 # define sensorPin
|
||||
led = LED(ledPin)
|
||||
sensor = MotionSensor(sensorPin)
|
||||
sensor.wait_for_no_motion()
|
||||
def loop():
|
||||
# Variables to hold the current and last states
|
||||
currentstate = False
|
||||
previousstate = False
|
||||
while True:
|
||||
# Read sensor state
|
||||
currentstate = sensor.motion_detected
|
||||
# If the sensor is triggered
|
||||
if currentstate == True and previousstate == False:
|
||||
led.on()
|
||||
print("Motion detected!led turned on >>>")
|
||||
# Record previous state
|
||||
previousstate = True
|
||||
# If the sensor has returned to ready state
|
||||
elif currentstate == False and previousstate == True:
|
||||
led.off()
|
||||
print("No Motion!led turned off <<")
|
||||
previousstate = False
|
||||
# Wait for 10 milliseconds
|
||||
time.sleep(0.01)
|
||||
|
||||
def destroy():
|
||||
led.close()
|
||||
sensor.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : UltrasonicRanging.py
|
||||
# Description : Get distance via UltrasonicRanging sensor
|
||||
# auther : www.freenove.com
|
||||
# modification: 2023/05/13
|
||||
########################################################################
|
||||
from gpiozero import DistanceSensor
|
||||
from time import sleep
|
||||
|
||||
trigPin = 23
|
||||
echoPin = 24
|
||||
sensor = DistanceSensor(echo=echoPin, trigger=trigPin ,max_distance=3)
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
print('Distance: ', sensor.distance * 100,'cm')
|
||||
sleep(1)
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
sensor.close()
|
||||
print("Ending program")
|
||||
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : UltrasonicRanging.py
|
||||
# Description : Get distance via UltrasonicRanging sensor
|
||||
# auther : www.freenove.com
|
||||
# modification: 2023/05/13
|
||||
########################################################################
|
||||
import os
|
||||
os.system("sudo pigpiod")
|
||||
from gpiozero import DistanceSensor
|
||||
from gpiozero.pins.pigpio import PiGPIOFactory
|
||||
from time import sleep
|
||||
|
||||
trigPin = 23
|
||||
echoPin = 24
|
||||
my_factory = PiGPIOFactory()
|
||||
sensor = DistanceSensor(echo=echoPin, trigger=trigPin ,max_distance=3,pin_factory=my_factory)
|
||||
|
||||
def loop():
|
||||
while True:
|
||||
print('Distance: ', sensor.distance * 100,'cm')
|
||||
sleep(1)
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
sensor.close()
|
||||
os.system("sudo killall pigpiod")
|
||||
print("Ending program")
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
MPU6050 Python I2C Class
|
||||
|
||||
Copyright (c) 2015 Geir Istad
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@@ -0,0 +1,946 @@
|
||||
__author__ = 'Geir Istad'
|
||||
"""
|
||||
MPU6050 Python I2C Class
|
||||
Copyright (c) 2015 Geir Istad
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
Code based on
|
||||
I2Cdev library collection - MPU6050 I2C device class
|
||||
by Jeff Rowberg <jeff@rowberg.net>
|
||||
============================================
|
||||
I2Cdev device library code is placed under the MIT license
|
||||
Copyright (c) 2012 Jeff Rowberg
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
===============================================
|
||||
"""
|
||||
|
||||
import math
|
||||
import ctypes
|
||||
import time
|
||||
import smbus
|
||||
import csv
|
||||
from MPUConstants import MPUConstants as C
|
||||
from Quaternion import Quaternion as Q
|
||||
from Quaternion import XYZVector as V
|
||||
|
||||
|
||||
class MPU6050:
|
||||
__buffer = [0] * 14
|
||||
__debug = False
|
||||
__DMP_packet_size = 0
|
||||
__dev_id = 0
|
||||
__bus = None
|
||||
|
||||
def __init__(self, a_bus=1, a_address=C.MPU6050_DEFAULT_ADDRESS,
|
||||
a_xAOff=None, a_yAOff=None, a_zAOff=None, a_xGOff=None,
|
||||
a_yGOff=None, a_zGOff=None, a_debug=False):
|
||||
self.__dev_id = a_address
|
||||
# Connect to num 1 SMBus
|
||||
self.__bus = smbus.SMBus(a_bus)
|
||||
# Set clock source to gyro
|
||||
self.set_clock_source(C.MPU6050_CLOCK_PLL_XGYRO)
|
||||
# Set accelerometer range
|
||||
self.set_full_scale_accel_range(C.MPU6050_ACCEL_FS_2)
|
||||
# Set gyro range
|
||||
self.set_full_scale_gyro_range(C.MPU6050_GYRO_FS_250)
|
||||
# Take the MPU out of time.sleep mode
|
||||
self.wake_up()
|
||||
# Set offsets
|
||||
if a_xAOff:
|
||||
self.set_x_accel_offset(a_xAOff)
|
||||
if a_yAOff:
|
||||
self.set_y_accel_offset(a_yAOff)
|
||||
if a_zAOff:
|
||||
self.set_z_accel_offset(a_zAOff)
|
||||
if a_xGOff:
|
||||
self.set_x_gyro_offset(a_xGOff)
|
||||
if a_yGOff:
|
||||
self.set_y_gyro_offset(a_yGOff)
|
||||
if a_zGOff:
|
||||
self.set_z_gyro_offset(a_zGOff)
|
||||
self.__debug = a_debug
|
||||
|
||||
# Core bit and byte operations
|
||||
def read_bit(self, a_reg_add, a_bit_position):
|
||||
return self.read_bits(a_reg_add, a_bit_position, 1)
|
||||
|
||||
def write_bit(self, a_reg_add, a_bit_num, a_bit):
|
||||
byte = self.__bus.read_byte_data(self.__dev_id, a_reg_add)
|
||||
if a_bit:
|
||||
byte |= 1 << a_bit_num
|
||||
else:
|
||||
byte &= ~(1 << a_bit_num)
|
||||
self.__bus.write_byte_data(
|
||||
self.__dev_id, a_reg_add, ctypes.c_int8(byte).value)
|
||||
|
||||
def read_bits(self, a_reg_add, a_bit_start, a_length):
|
||||
byte = self.__bus.read_byte_data(self.__dev_id, a_reg_add)
|
||||
mask = ((1 << a_length) - 1) << (a_bit_start - a_length + 1)
|
||||
byte &= mask
|
||||
byte >>= a_bit_start - a_length + 1
|
||||
return byte
|
||||
|
||||
def write_bits(self, a_reg_add, a_bit_start, a_length, a_data):
|
||||
byte = self.__bus.read_byte_data(self.__dev_id, a_reg_add)
|
||||
mask = ((1 << a_length) - 1) << (a_bit_start - a_length + 1)
|
||||
# Get data in position and zero all non-important bits in data
|
||||
a_data <<= a_bit_start - a_length + 1
|
||||
a_data &= mask
|
||||
# Clear all important bits in read byte and combine with data
|
||||
byte &= ~mask
|
||||
byte = byte | a_data
|
||||
# Write the data to the I2C device
|
||||
self.__bus.write_byte_data(
|
||||
self.__dev_id, a_reg_add, ctypes.c_int8(byte).value)
|
||||
|
||||
def read_memory_byte(self):
|
||||
return self.__bus.read_byte_data(self.__dev_id, C.MPU6050_RA_MEM_R_W)
|
||||
|
||||
def read_bytes(self, a_data_list, a_address, a_length):
|
||||
if a_length > len(a_data_list):
|
||||
print('read_bytes, length of passed list too short')
|
||||
return a_data_list
|
||||
# Attempt to use the built in read bytes function in the adafruit lib
|
||||
# a_data_list = self.__bus.read_i2c_block_data(self.__dev_id, a_address,
|
||||
# a_length)
|
||||
# Attempt to bypass adafruit lib
|
||||
#a_data_list = self.__mpu.bus.read_i2c_block_data(0x68, a_address, a_length)
|
||||
#print('data' + str(a_data_list))
|
||||
for x in range(0, a_length):
|
||||
a_data_list[x] = self.__bus.read_byte_data(self.__dev_id,
|
||||
a_address + x)
|
||||
return a_data_list
|
||||
|
||||
def write_memory_block(self, a_data_list, a_data_size, a_bank, a_address,
|
||||
a_verify):
|
||||
success = True
|
||||
self.set_memory_bank(a_bank)
|
||||
self.set_memory_start_address(a_address)
|
||||
|
||||
# For each a_data_item we want to write it to the board to a certain
|
||||
# memory bank and address
|
||||
for i in range(0, a_data_size):
|
||||
# Write each data to memory
|
||||
self.__bus.write_byte_data(self.__dev_id, C.MPU6050_RA_MEM_R_W,
|
||||
a_data_list[i])
|
||||
|
||||
if a_verify:
|
||||
self.set_memory_bank(a_bank)
|
||||
self.set_memory_start_address(a_address)
|
||||
verify_data = self.__bus.read_byte_data(self.__dev_id,
|
||||
C.MPU6050_RA_MEM_R_W)
|
||||
if verify_data != a_data_list[i]:
|
||||
success = False
|
||||
|
||||
# If we've filled the bank, change the memory bank
|
||||
if a_address == 255:
|
||||
a_address = 0
|
||||
a_bank += 1
|
||||
self.set_memory_bank(a_bank)
|
||||
else:
|
||||
a_address += 1
|
||||
|
||||
# Either way update the memory address
|
||||
self.set_memory_start_address(a_address)
|
||||
|
||||
return success
|
||||
|
||||
def wake_up(self):
|
||||
self.write_bit(
|
||||
C.MPU6050_RA_PWR_MGMT_1, C.MPU6050_PWR1_SLEEP_BIT, 0)
|
||||
|
||||
def set_clock_source(self, a_source):
|
||||
self.write_bits(C.MPU6050_RA_PWR_MGMT_1, C.MPU6050_PWR1_CLKSEL_BIT,
|
||||
C.MPU6050_PWR1_CLKSEL_LENGTH, a_source)
|
||||
|
||||
def set_full_scale_gyro_range(self, a_data):
|
||||
self.write_bits(C.MPU6050_RA_GYRO_CONFIG,
|
||||
C.MPU6050_GCONFIG_FS_SEL_BIT,
|
||||
C.MPU6050_GCONFIG_FS_SEL_LENGTH, a_data)
|
||||
|
||||
def set_full_scale_accel_range(self, a_data):
|
||||
self.write_bits(C.MPU6050_RA_ACCEL_CONFIG,
|
||||
C.MPU6050_ACONFIG_AFS_SEL_BIT,
|
||||
C.MPU6050_ACONFIG_AFS_SEL_LENGTH, a_data)
|
||||
|
||||
def reset(self):
|
||||
self.write_bit(C.MPU6050_RA_PWR_MGMT_1,
|
||||
C.MPU6050_PWR1_DEVICE_RESET_BIT, 1)
|
||||
|
||||
def set_sleep_enabled(self, a_enabled):
|
||||
set_bit = 0
|
||||
if a_enabled:
|
||||
set_bit = 1
|
||||
self.write_bit(C.MPU6050_RA_PWR_MGMT_1,
|
||||
C.MPU6050_PWR1_SLEEP_BIT, set_bit)
|
||||
|
||||
def set_memory_bank(self, a_bank, a_prefetch_enabled=False,
|
||||
a_user_bank=False):
|
||||
a_bank &= 0x1F
|
||||
if a_user_bank:
|
||||
a_bank |= 0x20
|
||||
if a_prefetch_enabled:
|
||||
a_bank |= 0x20
|
||||
self.__bus.write_byte_data(
|
||||
self.__dev_id, C.MPU6050_RA_BANK_SEL, a_bank)
|
||||
|
||||
def set_memory_start_address(self, a_address):
|
||||
self.__bus.write_byte_data(
|
||||
self.__dev_id, C.MPU6050_RA_MEM_START_ADDR, a_address)
|
||||
|
||||
def get_x_gyro_offset_TC(self):
|
||||
return self.read_bits(C.MPU6050_RA_XG_OFFS_TC,
|
||||
C.MPU6050_TC_OFFSET_BIT,
|
||||
C.MPU6050_TC_OFFSET_LENGTH)
|
||||
|
||||
def set_x_gyro_offset_TC(self, a_offset):
|
||||
self.write_bits(C.MPU6050_RA_XG_OFFS_TC,
|
||||
C.MPU6050_TC_OFFSET_BIT,
|
||||
C.MPU6050_TC_OFFSET_LENGTH, a_offset)
|
||||
|
||||
def get_y_gyro_offset_TC(self):
|
||||
return self.read_bits(C.MPU6050_RA_YG_OFFS_TC,
|
||||
C.MPU6050_TC_OFFSET_BIT,
|
||||
C.MPU6050_TC_OFFSET_LENGTH)
|
||||
|
||||
def set_y_gyro_offset_TC(self, a_offset):
|
||||
self.write_bits(C.MPU6050_RA_YG_OFFS_TC,
|
||||
C.MPU6050_TC_OFFSET_BIT,
|
||||
C.MPU6050_TC_OFFSET_LENGTH, a_offset)
|
||||
|
||||
def get_z_gyro_offset_TC(self):
|
||||
return self.read_bits(C.MPU6050_RA_ZG_OFFS_TC,
|
||||
C.MPU6050_TC_OFFSET_BIT,
|
||||
C.MPU6050_TC_OFFSET_LENGTH)
|
||||
|
||||
def set_z_gyro_offset_TC(self, a_offset):
|
||||
self.write_bits(C.MPU6050_RA_ZG_OFFS_TC,
|
||||
C.MPU6050_TC_OFFSET_BIT,
|
||||
C.MPU6050_TC_OFFSET_LENGTH, a_offset)
|
||||
|
||||
def set_slave_address(self, a_num, a_address):
|
||||
self.__bus.write_byte_data(
|
||||
self.__dev_id, C.MPU6050_RA_I2C_SLV0_ADDR + a_num * 3, a_address)
|
||||
|
||||
def set_I2C_master_mode_enabled(self, a_enabled):
|
||||
bit = 0
|
||||
if a_enabled:
|
||||
bit = 1
|
||||
self.write_bit(C.MPU6050_RA_USER_CTRL,
|
||||
C.MPU6050_USERCTRL_I2C_MST_EN_BIT, bit)
|
||||
|
||||
def reset_I2C_master(self):
|
||||
self.write_bit(C.MPU6050_RA_USER_CTRL,
|
||||
C.MPU6050_USERCTRL_I2C_MST_RESET_BIT, 1)
|
||||
|
||||
def write_prog_memory_block(self, a_data_list, a_data_size, a_bank=0,
|
||||
a_address=0, a_verify=True):
|
||||
return self.write_memory_block(a_data_list, a_data_size, a_bank,
|
||||
a_address, a_verify)
|
||||
|
||||
def write_DMP_configuration_set(self, a_data_list, a_data_size):
|
||||
index = 0
|
||||
while index < a_data_size:
|
||||
bank = a_data_list[index]
|
||||
offset = a_data_list[index + 1]
|
||||
length = a_data_list[index + 2]
|
||||
index += 3
|
||||
success = False
|
||||
|
||||
# Normal case
|
||||
if length > 0:
|
||||
data_selection = list()
|
||||
for subindex in range(0, length):
|
||||
data_selection.append(a_data_list[index + subindex])
|
||||
success = self.write_memory_block(data_selection, length, bank,
|
||||
offset, True)
|
||||
index += length
|
||||
# Special undocumented case
|
||||
else:
|
||||
special = a_data_list[index]
|
||||
index += 1
|
||||
if special == 0x01:
|
||||
# TODO Figure out if write8 can return True/False
|
||||
success = self.__bus.write_byte_data(
|
||||
self.__dev_id, C.MPU6050_RA_INT_ENABLE, 0x32)
|
||||
|
||||
if success == False:
|
||||
# TODO implement error messagemajigger
|
||||
return False
|
||||
pass
|
||||
return True
|
||||
|
||||
def write_prog_dmp_configuration(self, a_data_list, a_data_size):
|
||||
return self.write_DMP_configuration_set(a_data_list, a_data_size)
|
||||
|
||||
def set_int_enable(self, a_enabled):
|
||||
self.__bus.write_byte_data(
|
||||
self.__dev_id, C.MPU6050_RA_INT_ENABLE, a_enabled)
|
||||
|
||||
def set_rate(self, a_rate):
|
||||
self.__bus.write_byte_data(
|
||||
self.__dev_id, C.MPU6050_RA_SMPLRT_DIV, a_rate)
|
||||
|
||||
def set_external_frame_sync(self, a_sync):
|
||||
self.write_bits(C.MPU6050_RA_CONFIG,
|
||||
C.MPU6050_CFG_EXT_SYNC_SET_BIT,
|
||||
C.MPU6050_CFG_EXT_SYNC_SET_LENGTH, a_sync)
|
||||
|
||||
def set_DLF_mode(self, a_mode):
|
||||
self.write_bits(C.MPU6050_RA_CONFIG, C.MPU6050_CFG_DLPF_CFG_BIT,
|
||||
C.MPU6050_CFG_DLPF_CFG_LENGTH, a_mode)
|
||||
|
||||
def get_DMP_config_1(self):
|
||||
return self.__bus.read_byte_data(self.__dev_id, C.MPU6050_RA_DMP_CFG_1)
|
||||
|
||||
def set_DMP_config_1(self, a_config):
|
||||
self.__bus.write_byte_data(
|
||||
self.__dev_id, C.MPU6050_RA_DMP_CFG_1, a_config)
|
||||
|
||||
def get_DMP_config_2(self):
|
||||
return self.__bus.read_byte_data(self.__dev_id, C.MPU6050_RA_DMP_CFG_2)
|
||||
|
||||
def set_DMP_config_2(self, a_config):
|
||||
self.__bus.write_byte_data(
|
||||
self.__dev_id, C.MPU6050_RA_DMP_CFG_2, a_config)
|
||||
|
||||
def set_OTP_bank_valid(self, a_enabled):
|
||||
bit = 0
|
||||
if a_enabled:
|
||||
bit = 1
|
||||
self.write_bit(C.MPU6050_RA_XG_OFFS_TC,
|
||||
C.MPU6050_TC_OTP_BNK_VLD_BIT, bit)
|
||||
|
||||
def get_OTP_bank_valid(self):
|
||||
return self.read_bit(C.MPU6050_RA_XG_OFFS_TC,
|
||||
C.MPU6050_TC_OTP_BNK_VLD_BIT)
|
||||
|
||||
def set_motion_detection_threshold(self, a_threshold):
|
||||
self.__bus.write_byte_data(
|
||||
self.__dev_id, C.MPU6050_RA_MOT_THR, a_threshold)
|
||||
|
||||
def set_zero_motion_detection_threshold(self, a_threshold):
|
||||
self.__bus.write_byte_data(
|
||||
self.__dev_id, C.MPU6050_RA_ZRMOT_THR, a_threshold)
|
||||
|
||||
def set_motion_detection_duration(self, a_duration):
|
||||
self.__bus.write_byte_data(
|
||||
self.__dev_id, C.MPU6050_RA_MOT_DUR, a_duration)
|
||||
|
||||
def set_zero_motion_detection_duration(self, a_duration):
|
||||
self.__bus.write_byte_data(
|
||||
self.__dev_id, C.MPU6050_RA_ZRMOT_DUR, a_duration)
|
||||
|
||||
def set_FIFO_enabled(self, a_enabled):
|
||||
bit = 0
|
||||
if a_enabled:
|
||||
bit = 1
|
||||
self.write_bit(C.MPU6050_RA_USER_CTRL,
|
||||
C.MPU6050_USERCTRL_FIFO_EN_BIT, bit)
|
||||
|
||||
def set_DMP_enabled(self, a_enabled):
|
||||
bit = 0
|
||||
if a_enabled:
|
||||
bit = 1
|
||||
self.write_bit(C.MPU6050_RA_USER_CTRL,
|
||||
C.MPU6050_USERCTRL_DMP_EN_BIT, bit)
|
||||
|
||||
def reset_DMP(self):
|
||||
self.write_bit(C.MPU6050_RA_USER_CTRL,
|
||||
C.MPU6050_USERCTRL_DMP_RESET_BIT, True)
|
||||
|
||||
def dmp_initialize(self):
|
||||
# Reset the MPU
|
||||
self.reset()
|
||||
# time.Sleep a bit while resetting
|
||||
time.sleep(50 / 1000)
|
||||
# Disable time.sleep mode
|
||||
self.set_sleep_enabled(0)
|
||||
|
||||
# get MPU hardware revision
|
||||
if self.__debug:
|
||||
print('Selecting user bank 16')
|
||||
self.set_memory_bank(0x10, True, True)
|
||||
|
||||
if self.__debug:
|
||||
print('Selecting memory byte 6')
|
||||
self.set_memory_start_address(0x6)
|
||||
|
||||
if self.__debug:
|
||||
print('Checking hardware revision')
|
||||
HW_revision = self.read_memory_byte()
|
||||
if self.__debug:
|
||||
print('Revision @ user[16][6] = ' + hex(HW_revision))
|
||||
|
||||
if self.__debug:
|
||||
print('Resetting memory bank selection to 0')
|
||||
self.set_memory_bank(0)
|
||||
|
||||
# check OTP bank valid
|
||||
# TODO Find out what OTP is
|
||||
OTP_valid = self.get_OTP_bank_valid()
|
||||
if self.__debug:
|
||||
if OTP_valid:
|
||||
print('OTP bank is valid')
|
||||
else:
|
||||
print('OTP bank is invalid')
|
||||
|
||||
# get X/Y/Z gyro offsets
|
||||
if self.__debug:
|
||||
print('Reading gyro offet TC values')
|
||||
x_g_offset_TC = self.get_x_gyro_offset_TC()
|
||||
y_g_offset_TC = self.get_y_gyro_offset_TC()
|
||||
z_g_offset_TC = self.get_z_gyro_offset_TC()
|
||||
if self.__debug:
|
||||
print("X gyro offset = ", repr(x_g_offset_TC))
|
||||
print("Y gyro offset = ", repr(y_g_offset_TC))
|
||||
print("Z gyro offset = ", repr(z_g_offset_TC))
|
||||
|
||||
# setup weird slave stuff (?)
|
||||
if self.__debug:
|
||||
print('Setting slave 0 address to 0x7F')
|
||||
self.set_slave_address(0, 0x7F)
|
||||
if self.__debug:
|
||||
print('Disabling I2C Master mode')
|
||||
self.set_I2C_master_mode_enabled(False)
|
||||
if self.__debug:
|
||||
print('Setting slave 0 address to 0x68 (self)')
|
||||
self.set_slave_address(0, 0x68)
|
||||
if self.__debug:
|
||||
print('Resetting I2C Master control')
|
||||
self.reset_I2C_master()
|
||||
# Wait a bit for the device to register the changes
|
||||
time.sleep(20 / 1000)
|
||||
|
||||
# load DMP code into memory banks
|
||||
if self.__debug:
|
||||
print('Writing DMP code to MPU memory banks ' +
|
||||
repr(C.MPU6050_DMP_CODE_SIZE) + ' bytes')
|
||||
if self.write_prog_memory_block(C.dmpMemory, C.MPU6050_DMP_CODE_SIZE):
|
||||
# TODO Check if we've actually verified this
|
||||
if self.__debug:
|
||||
print('Success! DMP code written and verified')
|
||||
|
||||
# Write DMP configuration
|
||||
if self.__debug:
|
||||
print('Writing DMP configuration to MPU memory banks ' +
|
||||
repr(C.MPU6050_DMP_CONFIG_SIZE) + ' bytes in config')
|
||||
if self.write_prog_dmp_configuration(C.dmpConfig,
|
||||
C.MPU6050_DMP_CONFIG_SIZE):
|
||||
if self.__debug:
|
||||
print('Success! DMP configuration written and verified.')
|
||||
print('Setting clock source to Z gyro')
|
||||
self.set_clock_source(C.MPU6050_CLOCK_PLL_ZGYRO)
|
||||
|
||||
if self.__debug:
|
||||
print('Setting DMP and FIFO_OFLOW interrupts enabled')
|
||||
self.set_int_enable(0x12)
|
||||
|
||||
if self.__debug:
|
||||
print('Setting sample rate to 200Hz')
|
||||
self.set_rate(4)
|
||||
|
||||
if self.__debug:
|
||||
print('Setting external frame sync to TEMP_OUT_L[0]')
|
||||
self.set_external_frame_sync(C.MPU6050_EXT_SYNC_TEMP_OUT_L)
|
||||
|
||||
if self.__debug:
|
||||
print('Setting DLPF bandwidth to 42Hz')
|
||||
self.set_DLF_mode(C.MPU6050_DLPF_BW_42)
|
||||
|
||||
if self.__debug:
|
||||
print('Setting gyro sensitivity to +/- 2000 deg/sec')
|
||||
self.set_full_scale_gyro_range(C.MPU6050_GYRO_FS_2000)
|
||||
|
||||
if self.__debug:
|
||||
print('Setting DMP configuration bytes (function unknown)')
|
||||
self.set_DMP_config_1(0x03)
|
||||
self.set_DMP_config_2(0x00)
|
||||
|
||||
if self.__debug:
|
||||
print('Clearing OTP Bank flag')
|
||||
self.set_OTP_bank_valid(False)
|
||||
|
||||
if self.__debug:
|
||||
print('Setting X/Y/Z gyro offset TCs to previous values')
|
||||
self.set_x_gyro_offset_TC(x_g_offset_TC)
|
||||
self.set_y_gyro_offset_TC(y_g_offset_TC)
|
||||
self.set_z_gyro_offset_TC(z_g_offset_TC)
|
||||
|
||||
# Uncomment this to zero offsets when dmp_initialize is called
|
||||
# if self.__debug:
|
||||
# print('Setting X/Y/Z gyro user offsets to zero')
|
||||
# self.set_x_gyro_offset(0)
|
||||
# self.set_y_gyro_offset(0)
|
||||
# self.set_z_gyro_offset(0)
|
||||
|
||||
if self.__debug:
|
||||
print('Writing final memory update 1/7 (function unknown)')
|
||||
pos = 0
|
||||
j = 0
|
||||
dmp_update = [0] * 16
|
||||
while (j < 4) or (j < dmp_update[2] + 3):
|
||||
dmp_update[j] = C.dmpUpdates[pos]
|
||||
pos += 1
|
||||
j += 1
|
||||
# Write as block from pos 3
|
||||
self.write_memory_block(dmp_update[3:], dmp_update[2],
|
||||
dmp_update[0], dmp_update[1], True)
|
||||
|
||||
if self.__debug:
|
||||
print('Writing final memory update 2/7 (function unknown)')
|
||||
j = 0
|
||||
while (j < 4) or (j < dmp_update[2] + 3):
|
||||
dmp_update[j] = C.dmpUpdates[pos]
|
||||
pos += 1
|
||||
j += 1
|
||||
# Write as block from pos 3
|
||||
self.write_memory_block(dmp_update[3:], dmp_update[2],
|
||||
dmp_update[0], dmp_update[1], True)
|
||||
|
||||
if self.__debug:
|
||||
print('Resetting FIFO')
|
||||
self.reset_FIFO()
|
||||
|
||||
if self.__debug:
|
||||
print('Reading FIFO count')
|
||||
FIFO_count = self.get_FIFO_count()
|
||||
|
||||
if self.__debug:
|
||||
print('FIFO count: ' + repr(FIFO_count))
|
||||
|
||||
if self.__debug:
|
||||
print('Getting FIFO buffer')
|
||||
FIFO_buffer = [0] * 128
|
||||
FIFO_buffer = self.get_FIFO_bytes(FIFO_count)
|
||||
|
||||
if self.__debug:
|
||||
print('Setting motion detection threshold to 2')
|
||||
self.set_motion_detection_threshold(2)
|
||||
|
||||
if self.__debug:
|
||||
print('Setting zero-motion detection threshold to 156')
|
||||
self.set_zero_motion_detection_threshold(156)
|
||||
|
||||
if self.__debug:
|
||||
print('Setting motion detection duration to 80')
|
||||
self.set_motion_detection_duration(80)
|
||||
|
||||
if self.__debug:
|
||||
print('Setting zero-motion detection duration to 0')
|
||||
self.set_zero_motion_detection_duration(0)
|
||||
|
||||
if self.__debug:
|
||||
print('Resetting FIFO')
|
||||
self.reset_FIFO()
|
||||
|
||||
if self.__debug:
|
||||
print('Enabling FIFO')
|
||||
self.set_FIFO_enabled(True)
|
||||
|
||||
if self.__debug:
|
||||
print('Enabling DMP')
|
||||
self.set_DMP_enabled(True)
|
||||
|
||||
if self.__debug:
|
||||
print('Resetting DMP')
|
||||
self.reset_DMP()
|
||||
|
||||
if self.__debug:
|
||||
print('Writing final memory update 3/7 (function unknown)')
|
||||
j = 0
|
||||
while (j < 4) or (j < dmp_update[2] + 3):
|
||||
dmp_update[j] = C.dmpUpdates[pos]
|
||||
pos += 1
|
||||
j += 1
|
||||
# Write as block from pos 3
|
||||
self.write_memory_block(dmp_update[3:], dmp_update[2],
|
||||
dmp_update[0], dmp_update[1], True)
|
||||
|
||||
if self.__debug:
|
||||
print('Writing final memory update 4/7 (function unknown)')
|
||||
j = 0
|
||||
while (j < 4) or (j < dmp_update[2] + 3):
|
||||
dmp_update[j] = C.dmpUpdates[pos]
|
||||
pos += 1
|
||||
j += 1
|
||||
# Write as block from pos 3
|
||||
self.write_memory_block(dmp_update[3:], dmp_update[2],
|
||||
dmp_update[0], dmp_update[1], True)
|
||||
|
||||
if self.__debug:
|
||||
print('Writing final memory update 5/7 (function unknown)')
|
||||
j = 0
|
||||
while (j < 4) or (j < dmp_update[2] + 3):
|
||||
dmp_update[j] = C.dmpUpdates[pos]
|
||||
pos += 1
|
||||
j += 1
|
||||
# Write as block from pos 3
|
||||
self.write_memory_block(dmp_update[3:], dmp_update[2],
|
||||
dmp_update[0], dmp_update[1], True)
|
||||
|
||||
if self.__debug:
|
||||
print('Waiting for FIFO count > 2')
|
||||
FIFO_count = self.get_FIFO_count()
|
||||
while FIFO_count < 3:
|
||||
FIFO_count = self.get_FIFO_count()
|
||||
|
||||
if self.__debug:
|
||||
print('Current FIFO count = ' + repr(FIFO_count))
|
||||
print('Reading FIFO data')
|
||||
FIFO_buffer = self.get_FIFO_bytes(FIFO_count)
|
||||
|
||||
if self.__debug:
|
||||
print('Reading interrupt status')
|
||||
MPU_int_status = self.get_int_status()
|
||||
|
||||
if self.__debug:
|
||||
print('Current interrupt status = ' + hex(MPU_int_status))
|
||||
print('Writing final memory update 6/7 (function unknown)')
|
||||
j = 0
|
||||
while (j < 4) or (j < dmp_update[2] + 3):
|
||||
dmp_update[j] = C.dmpUpdates[pos]
|
||||
pos += 1
|
||||
j += 1
|
||||
# Write as block from pos 3
|
||||
self.write_memory_block(dmp_update[3:], dmp_update[2],
|
||||
dmp_update[0], dmp_update[1], True)
|
||||
|
||||
if self.__debug:
|
||||
print('Waiting for FIFO count > 2')
|
||||
FIFO_count = self.get_FIFO_count()
|
||||
while FIFO_count < 3:
|
||||
FIFO_count = self.get_FIFO_count()
|
||||
|
||||
if self.__debug:
|
||||
print('Current FIFO count = ' + repr(FIFO_count))
|
||||
print('Reading FIFO count')
|
||||
FIFO_buffer = self.get_FIFO_bytes(FIFO_count)
|
||||
|
||||
if self.__debug:
|
||||
print('Reading interrupt status')
|
||||
MPU_int_status = self.get_int_status()
|
||||
|
||||
if self.__debug:
|
||||
print('Current interrupt status = ' + hex(MPU_int_status))
|
||||
print('Writing final memory update 7/7 (function unknown)')
|
||||
j = 0
|
||||
while (j < 4) or (j < dmp_update[2] + 3):
|
||||
dmp_update[j] = C.dmpUpdates[pos]
|
||||
pos += 1
|
||||
j += 1
|
||||
# Write as block from pos 3
|
||||
self.write_memory_block(dmp_update[3:], dmp_update[2],
|
||||
dmp_update[0], dmp_update[1], True)
|
||||
|
||||
if self.__debug:
|
||||
print('DMP is good to go! Finally.')
|
||||
print('Disabling DMP (you turn it on later)')
|
||||
self.set_DMP_enabled(False)
|
||||
|
||||
if self.__debug:
|
||||
print('Setting up internal 42 byte DMP packet buffer')
|
||||
self.__DMP_packet_size = 42
|
||||
|
||||
if self.__debug:
|
||||
print(
|
||||
'Resetting FIFO and clearing INT status one last time')
|
||||
self.reset_FIFO()
|
||||
self.get_int_status()
|
||||
|
||||
else:
|
||||
if self.__debug:
|
||||
print('Configuration block loading failed')
|
||||
return 2
|
||||
|
||||
else:
|
||||
if self.__debug:
|
||||
print('Main binary block loading failed')
|
||||
return 1
|
||||
|
||||
if self.__debug:
|
||||
print('DMP initialization was successful')
|
||||
return 0
|
||||
|
||||
# Acceleration and gyro offset setters and getters
|
||||
def set_x_accel_offset(self, a_offset):
|
||||
self.__bus.write_byte_data(self.__dev_id, C.MPU6050_RA_XA_OFFS_H,
|
||||
ctypes.c_int8(a_offset >> 8).value)
|
||||
self.__bus.write_byte_data(self.__dev_id, C.MPU6050_RA_XA_OFFS_L_TC,
|
||||
ctypes.c_int8(a_offset).value)
|
||||
|
||||
def set_y_accel_offset(self, a_offset):
|
||||
self.__bus.write_byte_data(self.__dev_id, C.MPU6050_RA_YA_OFFS_H,
|
||||
ctypes.c_int8(a_offset >> 8).value)
|
||||
self.__bus.write_byte_data(self.__dev_id, C.MPU6050_RA_YA_OFFS_L_TC,
|
||||
ctypes.c_int8(a_offset).value)
|
||||
|
||||
def set_z_accel_offset(self, a_offset):
|
||||
self.__bus.write_byte_data(self.__dev_id, C.MPU6050_RA_ZA_OFFS_H,
|
||||
ctypes.c_int8(a_offset >> 8).value)
|
||||
self.__bus.write_byte_data(self.__dev_id, C.MPU6050_RA_ZA_OFFS_L_TC,
|
||||
ctypes.c_int8(a_offset).value)
|
||||
|
||||
def set_x_gyro_offset(self, a_offset):
|
||||
self.__bus.write_byte_data(self.__dev_id, C.MPU6050_RA_XG_OFFS_USRH,
|
||||
ctypes.c_int8(a_offset >> 8).value)
|
||||
self.__bus.write_byte_data(self.__dev_id, C.MPU6050_RA_XG_OFFS_USRL,
|
||||
ctypes.c_int8(a_offset).value)
|
||||
|
||||
def set_y_gyro_offset(self, a_offset):
|
||||
self.__bus.write_byte_data(self.__dev_id, C.MPU6050_RA_YG_OFFS_USRH,
|
||||
ctypes.c_int8(a_offset >> 8).value)
|
||||
self.__bus.write_byte_data(self.__dev_id, C.MPU6050_RA_YG_OFFS_USRL,
|
||||
ctypes.c_int8(a_offset).value)
|
||||
|
||||
def set_z_gyro_offset(self, a_offset):
|
||||
self.__bus.write_byte_data(self.__dev_id, C.MPU6050_RA_ZG_OFFS_USRH,
|
||||
ctypes.c_int8(a_offset >> 8).value)
|
||||
self.__bus.write_byte_data(self.__dev_id, C.MPU6050_RA_ZG_OFFS_USRL,
|
||||
ctypes.c_int8(a_offset).value)
|
||||
|
||||
# Main interfacing functions to get raw data from MPU
|
||||
def get_acceleration(self):
|
||||
raw_data = self.__bus.read_i2c_block_data(self.__dev_id,
|
||||
C.MPU6050_RA_ACCEL_XOUT_H, 6)
|
||||
accel = [0] * 3
|
||||
accel[0] = ctypes.c_int16(raw_data[0] << 8 | raw_data[1]).value
|
||||
accel[1] = ctypes.c_int16(raw_data[2] << 8 | raw_data[3]).value
|
||||
accel[2] = ctypes.c_int16(raw_data[4] << 8 | raw_data[5]).value
|
||||
return accel
|
||||
|
||||
def get_rotation(self):
|
||||
raw_data = self.__bus.read_i2c_block_data(self.__dev_id,
|
||||
C.MPU6050_RA_GYRO_XOUT_H, 6)
|
||||
gyro = [0] * 3
|
||||
gyro[0] = ctypes.c_int16(raw_data[0] << 8 | raw_data[1]).value
|
||||
gyro[1] = ctypes.c_int16(raw_data[2] << 8 | raw_data[3]).value
|
||||
gyro[2] = ctypes.c_int16(raw_data[4] << 8 | raw_data[5]).value
|
||||
return gyro
|
||||
|
||||
# Interfacing functions to get data from FIFO buffer
|
||||
def DMP_get_FIFO_packet_size(self):
|
||||
return self.__DMP_packet_size
|
||||
|
||||
def reset_FIFO(self):
|
||||
self.write_bit(C.MPU6050_RA_USER_CTRL,
|
||||
C.MPU6050_USERCTRL_FIFO_RESET_BIT, True)
|
||||
|
||||
def get_FIFO_count(self):
|
||||
data = [0] * 2
|
||||
data = self.read_bytes(data, C.MPU6050_RA_FIFO_COUNTH, 2)
|
||||
return (data[0] << 8) | data[1]
|
||||
|
||||
def get_FIFO_bytes(self, a_FIFO_count):
|
||||
return_list = list()
|
||||
for index in range(0, a_FIFO_count):
|
||||
return_list.append(
|
||||
self.__bus.read_byte_data(self.__dev_id,
|
||||
C.MPU6050_RA_FIFO_R_W))
|
||||
return return_list
|
||||
|
||||
def get_int_status(self):
|
||||
return self.__bus.read_byte_data(self.__dev_id,
|
||||
C.MPU6050_RA_INT_STATUS)
|
||||
|
||||
# Data retrieval from received FIFO buffer
|
||||
def DMP_get_quaternion_int16(self, a_FIFO_buffer):
|
||||
w = ctypes.c_int16((a_FIFO_buffer[0] << 8) | a_FIFO_buffer[1]).value
|
||||
x = ctypes.c_int16((a_FIFO_buffer[4] << 8) | a_FIFO_buffer[5]).value
|
||||
y = ctypes.c_int16((a_FIFO_buffer[8] << 8) | a_FIFO_buffer[9]).value
|
||||
z = ctypes.c_int16((a_FIFO_buffer[12] << 8) | a_FIFO_buffer[13]).value
|
||||
return Q(w, x, y, z)
|
||||
|
||||
def DMP_get_quaternion(self, a_FIFO_buffer):
|
||||
quat = self.DMP_get_quaternion_int16(a_FIFO_buffer)
|
||||
w = quat.w / 16384.0
|
||||
x = quat.x / 16384.0
|
||||
y = quat.y / 16384.0
|
||||
z = quat.z / 16384.0
|
||||
return Q(w, x, y, z)
|
||||
|
||||
def DMP_get_acceleration_int16(self, a_FIFO_buffer):
|
||||
x = ctypes.c_int16(a_FIFO_buffer[28] << 8 | a_FIFO_buffer[29]).value
|
||||
y = ctypes.c_int16(a_FIFO_buffer[32] << 8 | a_FIFO_buffer[33]).value
|
||||
z = ctypes.c_int16(a_FIFO_buffer[36] << 8 | a_FIFO_buffer[37]).value
|
||||
return V(x, y, z)
|
||||
|
||||
def DMP_get_gravity(self, a_quat):
|
||||
x = 2.0 * (a_quat.x * a_quat.z - a_quat.w * a_quat.y)
|
||||
y = 2.0 * (a_quat.w * a_quat.x + a_quat.y * a_quat.z)
|
||||
z = 1.0 * (a_quat.w * a_quat.w - a_quat.x * a_quat.x -
|
||||
a_quat.y * a_quat.y + a_quat.z * a_quat.z)
|
||||
return V(x, y, z)
|
||||
|
||||
def DMP_get_linear_accel_int16(self, a_v_raw, a_grav):
|
||||
x = ctypes.c_int16(a_v_raw.x - (a_grav.x*8192)).value
|
||||
y = ctypes.c_int16(a_v_raw.y - (a_grav.y*8192)).value
|
||||
y = ctypes.c_int16(a_v_raw.y - (a_grav.y*8192)).value
|
||||
return V(x, y, z)
|
||||
|
||||
def DMP_get_euler(self, a_quat):
|
||||
psi = math.atan2(2*a_quat.x*a_quat.y - 2*a_quat.w*a_quat.z,
|
||||
2*a_quat.w*a_quat.w + 2*a_quat.x*a_quat.x - 1)
|
||||
theta = -asin(2*a_quat.x*a_quat.z + 2*a_quat.w*a_quat.y)
|
||||
phi = math.atan2(2*a_quat.y*a_quat.z - 2*a_quat.w*a_quat.x,
|
||||
2*a_quat.w*a_quat.w + 2*a_quat.z*a_quat.z - 1)
|
||||
return V(psi, theta, phi)
|
||||
|
||||
def DMP_get_roll_pitch_yaw(self, a_quat, a_grav_vect):
|
||||
# roll: (tilt left/right, about X axis)
|
||||
roll = math.atan(a_grav_vect.y /
|
||||
math.sqrt(a_grav_vect.x*a_grav_vect.x +
|
||||
a_grav_vect.z*a_grav_vect.z))
|
||||
# pitch: (nose up/down, about Y axis)
|
||||
pitch = math.atan(a_grav_vect.x /
|
||||
math.sqrt(a_grav_vect.y*a_grav_vect.y +
|
||||
a_grav_vect.z*a_grav_vect.z))
|
||||
# yaw: (about Z axis)
|
||||
yaw = math.atan2(2*a_quat.x*a_quat.y - 2*a_quat.w*a_quat.z,
|
||||
2*a_quat.w*a_quat.w + 2*a_quat.x*a_quat.x - 1)
|
||||
return V(roll, pitch, yaw)
|
||||
|
||||
def DMP_get_euler_roll_pitch_yaw(self, a_quat, a_grav_vect):
|
||||
rad_ypr = self.DMP_get_roll_pitch_yaw(a_quat, a_grav_vect)
|
||||
roll = rad_ypr.x * (180.0/math.pi)
|
||||
pitch = rad_ypr.y * (180.0/math.pi)
|
||||
yaw = rad_ypr.z * (180.0/math.pi)
|
||||
return V(roll, pitch, yaw)
|
||||
|
||||
def DMP_get_linear_accel(self, a_vector_raw, a_vect_grav):
|
||||
x = a_vector_raw.x - a_vect_grav.x*8192
|
||||
y = a_vector_raw.y - a_vect_grav.y*8192
|
||||
z = a_vector_raw.z - a_vect_grav.z*8192
|
||||
return V(x, y, z)
|
||||
|
||||
|
||||
class MPU6050IRQHandler:
|
||||
__mpu = MPU6050
|
||||
__FIFO_buffer = list()
|
||||
__count = 0
|
||||
__packet_size = None
|
||||
__detected_error = False
|
||||
__logging = False
|
||||
__log_file = None
|
||||
__csv_writer = None
|
||||
__start_time = None
|
||||
__debug = None
|
||||
|
||||
# def __init__(self, a_i2c_bus, a_device_address, a_x_accel_offset,
|
||||
# a_y_accel_offset, a_z_accel_offset, a_x_gyro_offset,
|
||||
# a_y_gyro_offset, a_z_gyro_offset, a_enable_debug_output):
|
||||
# self.__mpu = MPU6050(a_i2c_bus, a_device_address, a_x_accel_offset,
|
||||
# a_y_accel_offset, a_z_accel_offset,
|
||||
# a_x_gyro_offset, a_y_gyro_offset, a_z_gyro_offset,
|
||||
# a_enable_debug_output)
|
||||
def __init__(self, a_mpu, a_logging=False, a_log_file='log.csv',
|
||||
a_debug=False):
|
||||
self.__mpu = a_mpu
|
||||
self.__FIFO_buffer = [0]*64
|
||||
self.__mpu.dmp_initialize()
|
||||
self.__mpu.set_DMP_enabled(True)
|
||||
self.__packet_size = self.__mpu.DMP_get_FIFO_packet_size()
|
||||
mpu_int_status = self.__mpu.get_int_status()
|
||||
if a_logging:
|
||||
self.__start_time = time.clock()
|
||||
self.__logging = True
|
||||
self.__log_file = open(a_log_file, 'ab')
|
||||
self.__csv_writer = csv.writer(self.__log_file, delimiter=',',
|
||||
quotechar='|',
|
||||
quoting=csv.QUOTE_MINIMAL)
|
||||
self.__debug = a_debug
|
||||
|
||||
def action(self, channel):
|
||||
if self.__detected_error:
|
||||
# Clear FIFO and reset MPU
|
||||
mpu_int_status = self.__mpu.get_int_status()
|
||||
self.__mpu.reset_FIFO()
|
||||
self.__detected_error = False
|
||||
return
|
||||
|
||||
try:
|
||||
FIFO_count = self.__mpu.get_FIFO_count()
|
||||
mpu_int_status = self.__mpu.get_int_status()
|
||||
except:
|
||||
self.__detected_error = True
|
||||
return
|
||||
|
||||
# If overflow is detected by status or fifo count we want to reset
|
||||
if (FIFO_count == 1024) or (mpu_int_status & 0x10):
|
||||
try:
|
||||
self.__mpu.reset_FIFO()
|
||||
except:
|
||||
self.__detected_error = True
|
||||
return
|
||||
|
||||
elif (mpu_int_status & 0x02):
|
||||
# Wait until packet_size number of bytes are ready for reading,
|
||||
# default is 42 bytes
|
||||
while FIFO_count < self.__packet_size:
|
||||
try:
|
||||
FIFO_count = self.__mpu.get_FIFO_count()
|
||||
except:
|
||||
self.__detected_error = True
|
||||
return
|
||||
|
||||
while FIFO_count > self.__packet_size:
|
||||
|
||||
try:
|
||||
self.__FIFO_buffer = \
|
||||
self.__mpu.get_FIFO_bytes(self.__packet_size)
|
||||
except:
|
||||
self.__detected_error = True
|
||||
return
|
||||
accel = \
|
||||
self.__mpu.DMP_get_acceleration_int16(self.__FIFO_buffer)
|
||||
quat = self.__mpu.DMP_get_quaternion_int16(self.__FIFO_buffer)
|
||||
grav = self.__mpu.DMP_get_gravity(quat)
|
||||
roll_pitch_yaw = self.__mpu.DMP_get_euler_roll_pitch_yaw(quat,
|
||||
grav)
|
||||
if self.__logging:
|
||||
delta_time = time.clock() - self.__start_time
|
||||
data_concat = ['%.4f' % delta_time] + \
|
||||
[accel.x, accel.y, accel.z] + \
|
||||
['%.3f' % roll_pitch_yaw.x,
|
||||
'%.3f' % roll_pitch_yaw.y,
|
||||
'%.3f' % roll_pitch_yaw.z]
|
||||
self.__csv_writer.writerow(data_concat)
|
||||
|
||||
if (self.__debug) and (self.__count % 100 == 0):
|
||||
print('roll: ' + str(roll_pitch_yaw.x))
|
||||
print('pitch: ' + str(roll_pitch_yaw.y))
|
||||
print('yaw: ' + str(roll_pitch_yaw.z))
|
||||
self.__count += 1
|
||||
FIFO_count -= self.__packet_size
|
||||
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
########################################################################
|
||||
# Filename : MPU6050RAW.py
|
||||
# Description : Read data of MPU6050.
|
||||
# auther : www.freenove.com
|
||||
# modification: 2019/12/28
|
||||
########################################################################
|
||||
import MPU6050
|
||||
import time
|
||||
|
||||
mpu = MPU6050.MPU6050() # instantiate a MPU6050 class object
|
||||
accel = [0]*3 # define an arry to store accelerometer data
|
||||
gyro = [0]*3 # define an arry to store gyroscope data
|
||||
def setup():
|
||||
mpu.dmp_initialize() # initialize MPU6050
|
||||
|
||||
def loop():
|
||||
while(True):
|
||||
accel = mpu.get_acceleration() # get accelerometer data
|
||||
gyro = mpu.get_rotation() # get gyroscope data
|
||||
print("a/g:%d\t%d\t%d\t%d\t%d\t%d "%(accel[0],accel[1],accel[2],gyro[0],gyro[1],gyro[2]))
|
||||
print("a/g:%.2f g\t%.2f g\t%.2f g\t%.2f d/s\t%.2f d/s\t%.2f d/s"%(accel[0]/16384.0,accel[1]/16384.0,
|
||||
accel[2]/16384.0,gyro[0]/131.0,gyro[1]/131.0,gyro[2]/131.0))
|
||||
time.sleep(0.1)
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print("Program is starting ... ")
|
||||
setup()
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
pass
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
from MPU6050 import MPU6050
|
||||
from SimplePID import SimplePID
|
||||
|
||||
|
||||
def avg_from_array(a_array):
|
||||
sum = 0.0
|
||||
for index in range(0, len(a_array)):
|
||||
sum += a_array[index]
|
||||
|
||||
return sum/len(a_array)
|
||||
|
||||
|
||||
i2c_bus = 1
|
||||
device_address = 0x68
|
||||
# The offsets are different for each device and should be changed
|
||||
# accordingly using a calibration procedure
|
||||
x_accel_offset = 0
|
||||
y_accel_offset = 0
|
||||
z_accel_offset =0
|
||||
x_gyro_offset = 0
|
||||
y_gyro_offset = 0
|
||||
z_gyro_offset = 0
|
||||
enable_debug_output = True
|
||||
|
||||
mpu = MPU6050(i2c_bus, device_address, x_accel_offset, y_accel_offset,
|
||||
z_accel_offset, x_gyro_offset, y_gyro_offset, z_gyro_offset,
|
||||
enable_debug_output)
|
||||
|
||||
kp = 0.03125
|
||||
ki = 0.25
|
||||
kd = 0
|
||||
|
||||
pidax = SimplePID(0, -15000, 15000, kp, ki, kd, 100, True)
|
||||
piday = SimplePID(0, -15000, 15000, kp, ki, kd, 100, True)
|
||||
pidaz = SimplePID(0, -15000, 15000, kp, ki, kd, 100, True)
|
||||
pidgx = SimplePID(0, -15000, 15000, kp, ki, kd, 100, True)
|
||||
pidgy = SimplePID(0, -15000, 15000, kp, ki, kd, 100, True)
|
||||
pidgz = SimplePID(0, -15000, 15000, kp, ki, kd, 100, True)
|
||||
|
||||
accel_reading = mpu.get_acceleration()
|
||||
|
||||
x_accel_reading = accel_reading[0]
|
||||
y_accel_reading = accel_reading[1]
|
||||
z_accel_reading = accel_reading[2]
|
||||
|
||||
x_accel_avg = [0]*100
|
||||
y_accel_avg = [0]*100
|
||||
z_accel_avg = [0]*100
|
||||
|
||||
x_accel_offset_avg = [0]*100
|
||||
y_accel_offset_avg = [0]*100
|
||||
z_accel_offset_avg = [0]*100
|
||||
|
||||
axindex = 0
|
||||
ayindex = 0
|
||||
azindex = 0
|
||||
|
||||
gyro_reading = mpu.get_rotation()
|
||||
|
||||
x_gyro_reading = gyro_reading[0]
|
||||
y_gyro_reading = gyro_reading[1]
|
||||
z_gyro_reading = gyro_reading[2]
|
||||
|
||||
x_gyro_avg = [0]*100
|
||||
y_gyro_avg = [0]*100
|
||||
z_gyro_avg = [0]*100
|
||||
|
||||
x_gyro_offset_avg = [0]*100
|
||||
y_gyro_offset_avg = [0]*100
|
||||
z_gyro_offset_avg = [0]*100
|
||||
|
||||
gxindex = 0
|
||||
gyindex = 0
|
||||
gzindex = 0
|
||||
|
||||
try:
|
||||
while True:
|
||||
accel_reading = mpu.get_acceleration()
|
||||
x_accel_reading = accel_reading[0]
|
||||
y_accel_reading = accel_reading[1]
|
||||
z_accel_reading = accel_reading[2]
|
||||
|
||||
gyro_reading = mpu.get_rotation()
|
||||
x_gyro_reading = gyro_reading[0]
|
||||
y_gyro_reading = gyro_reading[1]
|
||||
z_gyro_reading = gyro_reading[2]
|
||||
|
||||
if pidax.check_time():
|
||||
x_accel_offset = pidax.get_output_value(x_accel_reading)
|
||||
|
||||
mpu.set_x_accel_offset(int(x_accel_offset))
|
||||
|
||||
x_accel_avg[axindex] = x_accel_reading
|
||||
x_accel_offset_avg[axindex] = x_accel_offset
|
||||
|
||||
axindex += 1
|
||||
if axindex == len(x_accel_avg):
|
||||
axindex = 0
|
||||
print('x_avg_read: ' +
|
||||
str(avg_from_array(x_accel_avg)) +
|
||||
' x_avg_offset: ' +
|
||||
str(avg_from_array(x_accel_offset_avg)))
|
||||
print('y_avg_read: ' +
|
||||
str(avg_from_array(y_accel_avg)) +
|
||||
' y_avg_offset: ' +
|
||||
str(avg_from_array(y_accel_offset_avg)))
|
||||
print('z_avg_read: ' +
|
||||
str(avg_from_array(z_accel_avg)) +
|
||||
' z_avg_offset: ' +
|
||||
str(avg_from_array(z_accel_offset_avg)))
|
||||
|
||||
if piday.check_time():
|
||||
y_accel_offset = piday.get_output_value(y_accel_reading)
|
||||
|
||||
mpu.set_y_accel_offset(int(y_accel_offset))
|
||||
|
||||
y_accel_avg[ayindex] = y_accel_reading
|
||||
y_accel_offset_avg[ayindex] = y_accel_offset
|
||||
|
||||
ayindex += 1
|
||||
if ayindex == len(y_accel_avg):
|
||||
ayindex = 0
|
||||
|
||||
if pidaz.check_time():
|
||||
z_accel_offset = pidaz.get_output_value(z_accel_reading)
|
||||
|
||||
mpu.set_z_accel_offset(int(z_accel_offset))
|
||||
|
||||
z_accel_avg[azindex] = z_accel_reading
|
||||
z_accel_offset_avg[azindex] = z_accel_offset
|
||||
|
||||
azindex += 1
|
||||
if azindex == len(z_accel_avg):
|
||||
azindex = 0
|
||||
|
||||
# Gyro calibration
|
||||
if pidgx.check_time():
|
||||
x_gyro_offset = pidgx.get_output_value(x_gyro_reading)
|
||||
|
||||
mpu.set_x_gyro_offset(int(x_gyro_offset))
|
||||
|
||||
x_gyro_avg[gxindex] = x_gyro_reading
|
||||
x_gyro_offset_avg[gxindex] = x_gyro_offset
|
||||
|
||||
gxindex += 1
|
||||
if gxindex == len(x_gyro_avg):
|
||||
gxindex = 0
|
||||
print('x_avg_read: ' +
|
||||
str(avg_from_array(x_gyro_avg)) +
|
||||
' x_avg_offset: ' +
|
||||
str(avg_from_array(x_gyro_offset_avg)))
|
||||
print('y_avg_read: ' +
|
||||
str(avg_from_array(y_gyro_avg)) +
|
||||
' y_avg_offset: ' +
|
||||
str(avg_from_array(y_gyro_offset_avg)))
|
||||
print('z_avg_read: ' +
|
||||
str(avg_from_array(z_gyro_avg)) +
|
||||
' z_avg_offset: ' +
|
||||
str(avg_from_array(z_gyro_offset_avg)))
|
||||
|
||||
if pidgy.check_time():
|
||||
y_gyro_offset = pidgy.get_output_value(y_gyro_reading)
|
||||
|
||||
mpu.set_y_gyro_offset(int(y_gyro_offset))
|
||||
|
||||
y_gyro_avg[gyindex] = y_gyro_reading
|
||||
y_gyro_offset_avg[gyindex] = y_gyro_offset
|
||||
|
||||
gyindex += 1
|
||||
if gyindex == len(y_gyro_avg):
|
||||
gyindex = 0
|
||||
|
||||
if pidgz.check_time():
|
||||
z_gyro_offset = pidgz.get_output_value(z_gyro_reading)
|
||||
|
||||
mpu.set_z_gyro_offset(int(z_gyro_offset))
|
||||
|
||||
z_gyro_avg[gzindex] = z_gyro_reading
|
||||
z_gyro_offset_avg[gzindex] = z_gyro_offset
|
||||
|
||||
gzindex += 1
|
||||
if gzindex == len(z_gyro_avg):
|
||||
gzindex = 0
|
||||
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
@@ -0,0 +1,755 @@
|
||||
__author__ = 'Geir Istad'
|
||||
|
||||
'''
|
||||
MPU6050 Python I2C Class
|
||||
Copyright (c) 2015 Geir Istad
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
Code based on I2Cdev library collection - MPU6050 I2C device class
|
||||
by Jeff Rowberg <jeff@rowberg.net>
|
||||
============================================
|
||||
I2Cdev device library code is placed under the MIT license
|
||||
Copyright (c) 2012 Jeff Rowberg
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
===============================================
|
||||
'''
|
||||
|
||||
|
||||
class MPUConstants:
|
||||
# From MPU6050.h
|
||||
MPU6050_ADDRESS_AD0_LOW = 0x68 # address pin low (GND), default
|
||||
MPU6050_ADDRESS_AD0_HIGH = 0x69 # address pin high (VCC)
|
||||
MPU6050_DEFAULT_ADDRESS = MPU6050_ADDRESS_AD0_LOW
|
||||
|
||||
# [7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
|
||||
MPU6050_RA_XG_OFFS_TC = 0x00
|
||||
# [7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
|
||||
MPU6050_RA_YG_OFFS_TC = 0x01
|
||||
# [7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
|
||||
MPU6050_RA_ZG_OFFS_TC = 0x02
|
||||
# [7:0] X_FINE_GAIN
|
||||
MPU6050_RA_X_FINE_GAIN = 0x03
|
||||
# [7:0] Y_FINE_GAIN
|
||||
MPU6050_RA_Y_FINE_GAIN = 0x04
|
||||
# [7:0] Z_FINE_GAIN
|
||||
MPU6050_RA_Z_FINE_GAIN = 0x05
|
||||
# [15:0] XA_OFFS
|
||||
MPU6050_RA_XA_OFFS_H = 0x06
|
||||
MPU6050_RA_XA_OFFS_L_TC = 0x07
|
||||
# [15:0] YA_OFFS
|
||||
MPU6050_RA_YA_OFFS_H = 0x08
|
||||
MPU6050_RA_YA_OFFS_L_TC = 0x09
|
||||
# [15:0] ZA_OFFS
|
||||
MPU6050_RA_ZA_OFFS_H = 0x0A
|
||||
MPU6050_RA_ZA_OFFS_L_TC = 0x0B
|
||||
# [15:0] XG_OFFS_USR
|
||||
MPU6050_RA_XG_OFFS_USRH = 0x13
|
||||
MPU6050_RA_XG_OFFS_USRL = 0x14
|
||||
# [15:0] YG_OFFS_USR
|
||||
MPU6050_RA_YG_OFFS_USRH = 0x15
|
||||
MPU6050_RA_YG_OFFS_USRL = 0x16
|
||||
# [15:0] ZG_OFFS_USR
|
||||
MPU6050_RA_ZG_OFFS_USRH = 0x17
|
||||
MPU6050_RA_ZG_OFFS_USRL = 0x18
|
||||
MPU6050_RA_SMPLRT_DIV = 0x19
|
||||
MPU6050_RA_CONFIG = 0x1A
|
||||
MPU6050_RA_GYRO_CONFIG = 0x1B
|
||||
MPU6050_RA_ACCEL_CONFIG = 0x1C
|
||||
MPU6050_RA_FF_THR = 0x1D
|
||||
MPU6050_RA_FF_DUR = 0x1E
|
||||
MPU6050_RA_MOT_THR = 0x1F
|
||||
MPU6050_RA_MOT_DUR = 0x20
|
||||
MPU6050_RA_ZRMOT_THR = 0x21
|
||||
MPU6050_RA_ZRMOT_DUR = 0x22
|
||||
MPU6050_RA_FIFO_EN = 0x23
|
||||
MPU6050_RA_I2C_MST_CTRL = 0x24
|
||||
MPU6050_RA_I2C_SLV0_ADDR = 0x25
|
||||
MPU6050_RA_I2C_SLV0_REG = 0x26
|
||||
MPU6050_RA_I2C_SLV0_CTRL = 0x27
|
||||
MPU6050_RA_I2C_SLV1_ADDR = 0x28
|
||||
MPU6050_RA_I2C_SLV1_REG = 0x29
|
||||
MPU6050_RA_I2C_SLV1_CTRL = 0x2A
|
||||
MPU6050_RA_I2C_SLV2_ADDR = 0x2B
|
||||
MPU6050_RA_I2C_SLV2_REG = 0x2C
|
||||
MPU6050_RA_I2C_SLV2_CTRL = 0x2D
|
||||
MPU6050_RA_I2C_SLV3_ADDR = 0x2E
|
||||
MPU6050_RA_I2C_SLV3_REG = 0x2F
|
||||
MPU6050_RA_I2C_SLV3_CTRL = 0x30
|
||||
MPU6050_RA_I2C_SLV4_ADDR = 0x31
|
||||
MPU6050_RA_I2C_SLV4_REG = 0x32
|
||||
MPU6050_RA_I2C_SLV4_DO = 0x33
|
||||
MPU6050_RA_I2C_SLV4_CTRL = 0x34
|
||||
MPU6050_RA_I2C_SLV4_DI = 0x35
|
||||
MPU6050_RA_I2C_MST_STATUS = 0x36
|
||||
MPU6050_RA_INT_PIN_CFG = 0x37
|
||||
MPU6050_RA_INT_ENABLE = 0x38
|
||||
MPU6050_RA_DMP_INT_STATUS = 0x39
|
||||
MPU6050_RA_INT_STATUS = 0x3A
|
||||
MPU6050_RA_ACCEL_XOUT_H = 0x3B
|
||||
MPU6050_RA_ACCEL_XOUT_L = 0x3C
|
||||
MPU6050_RA_ACCEL_YOUT_H = 0x3D
|
||||
MPU6050_RA_ACCEL_YOUT_L = 0x3E
|
||||
MPU6050_RA_ACCEL_ZOUT_H = 0x3F
|
||||
MPU6050_RA_ACCEL_ZOUT_L = 0x40
|
||||
MPU6050_RA_TEMP_OUT_H = 0x41
|
||||
MPU6050_RA_TEMP_OUT_L = 0x42
|
||||
MPU6050_RA_GYRO_XOUT_H = 0x43
|
||||
MPU6050_RA_GYRO_XOUT_L = 0x44
|
||||
MPU6050_RA_GYRO_YOUT_H = 0x45
|
||||
MPU6050_RA_GYRO_YOUT_L = 0x46
|
||||
MPU6050_RA_GYRO_ZOUT_H = 0x47
|
||||
MPU6050_RA_GYRO_ZOUT_L = 0x48
|
||||
MPU6050_RA_EXT_SENS_DATA_00 = 0x49
|
||||
MPU6050_RA_EXT_SENS_DATA_01 = 0x4A
|
||||
MPU6050_RA_EXT_SENS_DATA_02 = 0x4B
|
||||
MPU6050_RA_EXT_SENS_DATA_03 = 0x4C
|
||||
MPU6050_RA_EXT_SENS_DATA_04 = 0x4D
|
||||
MPU6050_RA_EXT_SENS_DATA_05 = 0x4E
|
||||
MPU6050_RA_EXT_SENS_DATA_06 = 0x4F
|
||||
MPU6050_RA_EXT_SENS_DATA_07 = 0x50
|
||||
MPU6050_RA_EXT_SENS_DATA_08 = 0x51
|
||||
MPU6050_RA_EXT_SENS_DATA_09 = 0x52
|
||||
MPU6050_RA_EXT_SENS_DATA_10 = 0x53
|
||||
MPU6050_RA_EXT_SENS_DATA_11 = 0x54
|
||||
MPU6050_RA_EXT_SENS_DATA_12 = 0x55
|
||||
MPU6050_RA_EXT_SENS_DATA_13 = 0x56
|
||||
MPU6050_RA_EXT_SENS_DATA_14 = 0x57
|
||||
MPU6050_RA_EXT_SENS_DATA_15 = 0x58
|
||||
MPU6050_RA_EXT_SENS_DATA_16 = 0x59
|
||||
MPU6050_RA_EXT_SENS_DATA_17 = 0x5A
|
||||
MPU6050_RA_EXT_SENS_DATA_18 = 0x5B
|
||||
MPU6050_RA_EXT_SENS_DATA_19 = 0x5C
|
||||
MPU6050_RA_EXT_SENS_DATA_20 = 0x5D
|
||||
MPU6050_RA_EXT_SENS_DATA_21 = 0x5E
|
||||
MPU6050_RA_EXT_SENS_DATA_22 = 0x5F
|
||||
MPU6050_RA_EXT_SENS_DATA_23 = 0x60
|
||||
MPU6050_RA_MOT_DETECT_STATUS = 0x61
|
||||
MPU6050_RA_I2C_SLV0_DO = 0x63
|
||||
MPU6050_RA_I2C_SLV1_DO = 0x64
|
||||
MPU6050_RA_I2C_SLV2_DO = 0x65
|
||||
MPU6050_RA_I2C_SLV3_DO = 0x66
|
||||
MPU6050_RA_I2C_MST_DELAY_CTRL = 0x67
|
||||
MPU6050_RA_SIGNAL_PATH_RESET = 0x68
|
||||
MPU6050_RA_MOT_DETECT_CTRL = 0x69
|
||||
MPU6050_RA_USER_CTRL = 0x6A
|
||||
MPU6050_RA_PWR_MGMT_1 = 0x6B
|
||||
MPU6050_RA_PWR_MGMT_2 = 0x6C
|
||||
MPU6050_RA_BANK_SEL = 0x6D
|
||||
MPU6050_RA_MEM_START_ADDR = 0x6E
|
||||
MPU6050_RA_MEM_R_W = 0x6F
|
||||
MPU6050_RA_DMP_CFG_1 = 0x70
|
||||
MPU6050_RA_DMP_CFG_2 = 0x71
|
||||
MPU6050_RA_FIFO_COUNTH = 0x72
|
||||
MPU6050_RA_FIFO_COUNTL = 0x73
|
||||
MPU6050_RA_FIFO_R_W = 0x74
|
||||
MPU6050_RA_WHO_AM_I = 0x75
|
||||
|
||||
MPU6050_TC_PWR_MODE_BIT = 7
|
||||
MPU6050_TC_OFFSET_BIT = 6
|
||||
MPU6050_TC_OFFSET_LENGTH = 6
|
||||
MPU6050_TC_OTP_BNK_VLD_BIT = 0
|
||||
|
||||
MPU6050_VDDIO_LEVEL_VLOGIC = 0
|
||||
MPU6050_VDDIO_LEVEL_VDD = 1
|
||||
|
||||
MPU6050_CFG_EXT_SYNC_SET_BIT = 5
|
||||
MPU6050_CFG_EXT_SYNC_SET_LENGTH = 3
|
||||
MPU6050_CFG_DLPF_CFG_BIT = 2
|
||||
MPU6050_CFG_DLPF_CFG_LENGTH = 3
|
||||
|
||||
MPU6050_EXT_SYNC_DISABLED = 0x0
|
||||
MPU6050_EXT_SYNC_TEMP_OUT_L = 0x1
|
||||
MPU6050_EXT_SYNC_GYRO_XOUT_L = 0x2
|
||||
MPU6050_EXT_SYNC_GYRO_YOUT_L = 0x3
|
||||
MPU6050_EXT_SYNC_GYRO_ZOUT_L = 0x4
|
||||
MPU6050_EXT_SYNC_ACCEL_XOUT_L = 0x5
|
||||
MPU6050_EXT_SYNC_ACCEL_YOUT_L = 0x6
|
||||
MPU6050_EXT_SYNC_ACCEL_ZOUT_L = 0x7
|
||||
|
||||
MPU6050_DLPF_BW_256 = 0x00
|
||||
MPU6050_DLPF_BW_188 = 0x01
|
||||
MPU6050_DLPF_BW_98 = 0x02
|
||||
MPU6050_DLPF_BW_42 = 0x03
|
||||
MPU6050_DLPF_BW_20 = 0x04
|
||||
MPU6050_DLPF_BW_10 = 0x05
|
||||
MPU6050_DLPF_BW_5 = 0x06
|
||||
|
||||
MPU6050_GCONFIG_FS_SEL_BIT = 4
|
||||
MPU6050_GCONFIG_FS_SEL_LENGTH = 2
|
||||
|
||||
MPU6050_GYRO_FS_250 = 0x00
|
||||
MPU6050_GYRO_FS_500 = 0x01
|
||||
MPU6050_GYRO_FS_1000 = 0x02
|
||||
MPU6050_GYRO_FS_2000 = 0x03
|
||||
|
||||
MPU6050_ACONFIG_XA_ST_BIT = 7
|
||||
MPU6050_ACONFIG_YA_ST_BIT = 6
|
||||
MPU6050_ACONFIG_ZA_ST_BIT = 5
|
||||
MPU6050_ACONFIG_AFS_SEL_BIT = 4
|
||||
MPU6050_ACONFIG_AFS_SEL_LENGTH = 2
|
||||
MPU6050_ACONFIG_ACCEL_HPF_BIT = 2
|
||||
MPU6050_ACONFIG_ACCEL_HPF_LENGTH = 3
|
||||
|
||||
MPU6050_ACCEL_FS_2 = 0x00
|
||||
MPU6050_ACCEL_FS_4 = 0x01
|
||||
MPU6050_ACCEL_FS_8 = 0x02
|
||||
MPU6050_ACCEL_FS_16 = 0x03
|
||||
|
||||
MPU6050_DHPF_RESET = 0x00
|
||||
MPU6050_DHPF_5 = 0x01
|
||||
MPU6050_DHPF_2P5 = 0x02
|
||||
MPU6050_DHPF_1P25 = 0x03
|
||||
MPU6050_DHPF_0P63 = 0x04
|
||||
MPU6050_DHPF_HOLD = 0x07
|
||||
|
||||
MPU6050_TEMP_FIFO_EN_BIT = 7
|
||||
MPU6050_XG_FIFO_EN_BIT = 6
|
||||
MPU6050_YG_FIFO_EN_BIT = 5
|
||||
MPU6050_ZG_FIFO_EN_BIT = 4
|
||||
MPU6050_ACCEL_FIFO_EN_BIT = 3
|
||||
MPU6050_SLV2_FIFO_EN_BIT = 2
|
||||
MPU6050_SLV1_FIFO_EN_BIT = 1
|
||||
MPU6050_SLV0_FIFO_EN_BIT = 0
|
||||
|
||||
MPU6050_MULT_MST_EN_BIT = 7
|
||||
MPU6050_WAIT_FOR_ES_BIT = 6
|
||||
MPU6050_SLV_3_FIFO_EN_BIT = 5
|
||||
MPU6050_I2C_MST_P_NSR_BIT = 4
|
||||
MPU6050_I2C_MST_CLK_BIT = 3
|
||||
MPU6050_I2C_MST_CLK_LENGTH = 4
|
||||
|
||||
MPU6050_CLOCK_DIV_348 = 0x0
|
||||
MPU6050_CLOCK_DIV_333 = 0x1
|
||||
MPU6050_CLOCK_DIV_320 = 0x2
|
||||
MPU6050_CLOCK_DIV_308 = 0x3
|
||||
MPU6050_CLOCK_DIV_296 = 0x4
|
||||
MPU6050_CLOCK_DIV_286 = 0x5
|
||||
MPU6050_CLOCK_DIV_276 = 0x6
|
||||
MPU6050_CLOCK_DIV_267 = 0x7
|
||||
MPU6050_CLOCK_DIV_258 = 0x8
|
||||
MPU6050_CLOCK_DIV_500 = 0x9
|
||||
MPU6050_CLOCK_DIV_471 = 0xA
|
||||
MPU6050_CLOCK_DIV_444 = 0xB
|
||||
MPU6050_CLOCK_DIV_421 = 0xC
|
||||
MPU6050_CLOCK_DIV_400 = 0xD
|
||||
MPU6050_CLOCK_DIV_381 = 0xE
|
||||
MPU6050_CLOCK_DIV_364 = 0xF
|
||||
|
||||
MPU6050_I2C_SLV_RW_BIT = 7
|
||||
MPU6050_I2C_SLV_ADDR_BIT = 6
|
||||
MPU6050_I2C_SLV_ADDR_LENGTH = 7
|
||||
MPU6050_I2C_SLV_EN_BIT = 7
|
||||
MPU6050_I2C_SLV_BYTE_SW_BIT = 6
|
||||
MPU6050_I2C_SLV_REG_DIS_BIT = 5
|
||||
MPU6050_I2C_SLV_GRP_BIT = 4
|
||||
MPU6050_I2C_SLV_LEN_BIT = 3
|
||||
MPU6050_I2C_SLV_LEN_LENGTH = 4
|
||||
|
||||
MPU6050_I2C_SLV4_RW_BIT = 7
|
||||
MPU6050_I2C_SLV4_ADDR_BIT = 6
|
||||
MPU6050_I2C_SLV4_ADDR_LENGTH = 7
|
||||
MPU6050_I2C_SLV4_EN_BIT = 7
|
||||
MPU6050_I2C_SLV4_INT_EN_BIT = 6
|
||||
MPU6050_I2C_SLV4_REG_DIS_BIT = 5
|
||||
MPU6050_I2C_SLV4_MST_DLY_BIT = 4
|
||||
MPU6050_I2C_SLV4_MST_DLY_LENGTH = 5
|
||||
|
||||
MPU6050_MST_PASS_THROUGH_BIT = 7
|
||||
MPU6050_MST_I2C_SLV4_DONE_BIT = 6
|
||||
MPU6050_MST_I2C_LOST_ARB_BIT = 5
|
||||
MPU6050_MST_I2C_SLV4_NACK_BIT = 4
|
||||
MPU6050_MST_I2C_SLV3_NACK_BIT = 3
|
||||
MPU6050_MST_I2C_SLV2_NACK_BIT = 2
|
||||
MPU6050_MST_I2C_SLV1_NACK_BIT = 1
|
||||
MPU6050_MST_I2C_SLV0_NACK_BIT = 0
|
||||
|
||||
MPU6050_INTCFG_INT_LEVEL_BIT = 7
|
||||
MPU6050_INTCFG_INT_OPEN_BIT = 6
|
||||
MPU6050_INTCFG_LATCH_INT_EN_BIT = 5
|
||||
MPU6050_INTCFG_INT_RD_CLEAR_BIT = 4
|
||||
MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT = 3
|
||||
MPU6050_INTCFG_FSYNC_INT_EN_BIT = 2
|
||||
MPU6050_INTCFG_I2C_BYPASS_EN_BIT = 1
|
||||
MPU6050_INTCFG_CLKOUT_EN_BIT = 0
|
||||
|
||||
MPU6050_INTMODE_ACTIVEHIGH = 0x00
|
||||
MPU6050_INTMODE_ACTIVELOW = 0x01
|
||||
|
||||
MPU6050_INTDRV_PUSHPULL = 0x00
|
||||
MPU6050_INTDRV_OPENDRAIN = 0x01
|
||||
|
||||
MPU6050_INTLATCH_50USPULSE = 0x00
|
||||
MPU6050_INTLATCH_WAITCLEAR = 0x01
|
||||
|
||||
MPU6050_INTCLEAR_STATUSREAD = 0x00
|
||||
MPU6050_INTCLEAR_ANYREAD = 0x01
|
||||
|
||||
MPU6050_INTERRUPT_FF_BIT = 7
|
||||
MPU6050_INTERRUPT_MOT_BIT = 6
|
||||
MPU6050_INTERRUPT_ZMOT_BIT = 5
|
||||
MPU6050_INTERRUPT_FIFO_OFLOW_BIT = 4
|
||||
MPU6050_INTERRUPT_I2C_MST_INT_BIT = 3
|
||||
MPU6050_INTERRUPT_PLL_RDY_INT_BIT = 2
|
||||
MPU6050_INTERRUPT_DMP_INT_BIT = 1
|
||||
MPU6050_INTERRUPT_DATA_RDY_BIT = 0
|
||||
|
||||
# TODO: figure out what these actually do
|
||||
# UMPL source code is not very obivous
|
||||
MPU6050_DMPINT_5_BIT = 5
|
||||
MPU6050_DMPINT_4_BIT = 4
|
||||
MPU6050_DMPINT_3_BIT = 3
|
||||
MPU6050_DMPINT_2_BIT = 2
|
||||
MPU6050_DMPINT_1_BIT = 1
|
||||
MPU6050_DMPINT_0_BIT = 0
|
||||
|
||||
MPU6050_MOTION_MOT_XNEG_BIT = 7
|
||||
MPU6050_MOTION_MOT_XPOS_BIT = 6
|
||||
MPU6050_MOTION_MOT_YNEG_BIT = 5
|
||||
MPU6050_MOTION_MOT_YPOS_BIT = 4
|
||||
MPU6050_MOTION_MOT_ZNEG_BIT = 3
|
||||
MPU6050_MOTION_MOT_ZPOS_BIT = 2
|
||||
MPU6050_MOTION_MOT_ZRMOT_BIT = 0
|
||||
|
||||
MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT = 7
|
||||
MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT = 4
|
||||
MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT = 3
|
||||
MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT = 2
|
||||
MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT = 1
|
||||
MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT = 0
|
||||
|
||||
MPU6050_PATHRESET_GYRO_RESET_BIT = 2
|
||||
MPU6050_PATHRESET_ACCEL_RESET_BIT = 1
|
||||
MPU6050_PATHRESET_TEMP_RESET_BIT = 0
|
||||
|
||||
MPU6050_DETECT_ACCEL_ON_DELAY_BIT = 5
|
||||
MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH = 2
|
||||
MPU6050_DETECT_FF_COUNT_BIT = 3
|
||||
MPU6050_DETECT_FF_COUNT_LENGTH = 2
|
||||
MPU6050_DETECT_MOT_COUNT_BIT = 1
|
||||
MPU6050_DETECT_MOT_COUNT_LENGTH = 2
|
||||
|
||||
MPU6050_DETECT_DECREMENT_RESET = 0x0
|
||||
MPU6050_DETECT_DECREMENT_1 = 0x1
|
||||
MPU6050_DETECT_DECREMENT_2 = 0x2
|
||||
MPU6050_DETECT_DECREMENT_4 = 0x3
|
||||
|
||||
MPU6050_USERCTRL_DMP_EN_BIT = 7
|
||||
MPU6050_USERCTRL_FIFO_EN_BIT = 6
|
||||
MPU6050_USERCTRL_I2C_MST_EN_BIT = 5
|
||||
MPU6050_USERCTRL_I2C_IF_DIS_BIT = 4
|
||||
MPU6050_USERCTRL_DMP_RESET_BIT = 3
|
||||
MPU6050_USERCTRL_FIFO_RESET_BIT = 2
|
||||
MPU6050_USERCTRL_I2C_MST_RESET_BIT = 1
|
||||
MPU6050_USERCTRL_SIG_COND_RESET_BIT = 0
|
||||
|
||||
MPU6050_PWR1_DEVICE_RESET_BIT = 7
|
||||
MPU6050_PWR1_SLEEP_BIT = 6
|
||||
MPU6050_PWR1_CYCLE_BIT = 5
|
||||
MPU6050_PWR1_TEMP_DIS_BIT = 3
|
||||
MPU6050_PWR1_CLKSEL_BIT = 2
|
||||
MPU6050_PWR1_CLKSEL_LENGTH = 3
|
||||
|
||||
MPU6050_CLOCK_INTERNAL = 0x00
|
||||
MPU6050_CLOCK_PLL_XGYRO = 0x01
|
||||
MPU6050_CLOCK_PLL_YGYRO = 0x02
|
||||
MPU6050_CLOCK_PLL_ZGYRO = 0x03
|
||||
MPU6050_CLOCK_PLL_EXT32K = 0x04
|
||||
MPU6050_CLOCK_PLL_EXT19M = 0x05
|
||||
MPU6050_CLOCK_KEEP_RESET = 0x07
|
||||
|
||||
MPU6050_PWR2_LP_WAKE_CTRL_BIT = 7
|
||||
MPU6050_PWR2_LP_WAKE_CTRL_LENGTH = 2
|
||||
MPU6050_PWR2_STBY_XA_BIT = 5
|
||||
MPU6050_PWR2_STBY_YA_BIT = 4
|
||||
MPU6050_PWR2_STBY_ZA_BIT = 3
|
||||
MPU6050_PWR2_STBY_XG_BIT = 2
|
||||
MPU6050_PWR2_STBY_YG_BIT = 1
|
||||
MPU6050_PWR2_STBY_ZG_BIT = 0
|
||||
|
||||
MPU6050_WAKE_FREQ_1P25 = 0x0
|
||||
MPU6050_WAKE_FREQ_2P5 = 0x1
|
||||
MPU6050_WAKE_FREQ_5 = 0x2
|
||||
MPU6050_WAKE_FREQ_10 = 0x3
|
||||
|
||||
MPU6050_BANKSEL_PRFTCH_EN_BIT = 6
|
||||
MPU6050_BANKSEL_CFG_USER_BANK_BIT = 5
|
||||
MPU6050_BANKSEL_MEM_SEL_BIT = 4
|
||||
MPU6050_BANKSEL_MEM_SEL_LENGTH = 5
|
||||
|
||||
MPU6050_WHO_AM_I_BIT = 6
|
||||
MPU6050_WHO_AM_I_LENGTH = 6
|
||||
|
||||
MPU6050_DMP_MEMORY_BANKS = 8
|
||||
MPU6050_DMP_MEMORY_BANK_SIZE = 256
|
||||
MPU6050_DMP_MEMORY_CHUNK_SIZE = 16
|
||||
|
||||
# From MPU6050_6Axis_MotionApps20.h
|
||||
MPU6050_DMP_CODE_SIZE = 1929 # dmpMemory[]
|
||||
MPU6050_DMP_CONFIG_SIZE = 192 # dmpConfig[]
|
||||
MPU6050_DMP_UPDATES_SIZE = 47 # dmpUpdates[]
|
||||
'''
|
||||
* ================================================================================================ *
|
||||
| Default MotionApps v2.0 42-byte FIFO packet structure: |
|
||||
| |
|
||||
| [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] |
|
||||
| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
||||
| |
|
||||
| [GYRO Z][ ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] |
|
||||
| 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
||||
* ================================================================================================ *
|
||||
'''
|
||||
# dmpMemory has size MPU6050_DMP_CODE_SIZE = 1929
|
||||
dmpMemory = [
|
||||
# bank 0, 256 bytes
|
||||
0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02,
|
||||
0x00, 0x03, 0x00, 0x00,
|
||||
0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B,
|
||||
0x12, 0x82, 0x00, 0x01,
|
||||
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF,
|
||||
0xFF, 0xFE, 0x80, 0x01,
|
||||
0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09,
|
||||
0x3E, 0x80, 0x00, 0x00,
|
||||
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
|
||||
0x60, 0x00, 0x00, 0x00,
|
||||
0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55,
|
||||
0x00, 0x00, 0x21, 0x82,
|
||||
0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00,
|
||||
0x00, 0x05, 0x80, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
|
||||
0x00, 0x03, 0x00, 0x00,
|
||||
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32,
|
||||
0x00, 0x00, 0x5E, 0xC0,
|
||||
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B,
|
||||
0x00, 0x6C, 0x12, 0xCC,
|
||||
0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00,
|
||||
0x40, 0x00, 0x01, 0xF4,
|
||||
0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6,
|
||||
0x00, 0x00, 0x27, 0x10,
|
||||
|
||||
# bank 1, 256 bytes
|
||||
0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0,
|
||||
0xFF, 0xD9, 0x5B, 0xC8,
|
||||
0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2,
|
||||
0x00, 0xCE, 0xBB, 0xF7,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02,
|
||||
0x02, 0x00, 0x00, 0x0C,
|
||||
0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00,
|
||||
0x40, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
|
||||
0x00, 0x00, 0x00, 0x14,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC,
|
||||
0xC6, 0x7E, 0xD1, 0x6C,
|
||||
0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0,
|
||||
0x00, 0x00, 0x00, 0x30,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE,
|
||||
0x00, 0x0C, 0x02, 0xD0,
|
||||
|
||||
# bank 2, 256 bytes
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00,
|
||||
0x00, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00,
|
||||
0xFF, 0xEF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x40, 0x00, 0x00, 0x00,
|
||||
0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
# bank 3, 256 bytes
|
||||
0xD8, 0xDC, 0xBA, 0xA2, 0xF1, 0xDE, 0xB2, 0xB8, 0xB4, 0xA8, 0x81, 0x91,
|
||||
0xF7, 0x4A, 0x90, 0x7F,
|
||||
0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, 0xA0, 0x80, 0xF2,
|
||||
0xCE, 0x81, 0xF3, 0xC2,
|
||||
0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, 0xF1, 0xC6, 0xD8,
|
||||
0x80, 0xBA, 0xA7, 0xDF,
|
||||
0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, 0x87, 0xA2, 0x94,
|
||||
0x24, 0x48, 0x70, 0x3C,
|
||||
0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, 0x83, 0x92, 0x2D,
|
||||
0x55, 0x7D, 0xD8, 0xB1,
|
||||
0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, 0x70, 0xF2, 0x7C,
|
||||
0x80, 0xA8, 0xF1, 0x01,
|
||||
0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, 0xBA, 0xA1, 0xF2,
|
||||
0x0E, 0xB8, 0x97, 0x80,
|
||||
0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0xC5,
|
||||
0xCD, 0xC7, 0xA9, 0x0C,
|
||||
0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, 0x26, 0x46, 0x66,
|
||||
0xB0, 0xB4, 0xBA, 0x80,
|
||||
0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, 0xB6, 0x98, 0x00,
|
||||
0x89, 0x0E, 0x16, 0x1E,
|
||||
0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, 0xA8, 0x96, 0x36,
|
||||
0x56, 0x76, 0xF1, 0xB9,
|
||||
0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB1, 0x8F, 0x98,
|
||||
0xB9, 0xAF, 0xF0, 0x24,
|
||||
0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, 0x7D, 0xAF, 0x83,
|
||||
0xB5, 0x93, 0xAF, 0xF0,
|
||||
0x00, 0x28, 0x50, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF,
|
||||
0xD9, 0xFA, 0xA3, 0x86,
|
||||
0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5,
|
||||
0xC7, 0xB2, 0x8C, 0xC1,
|
||||
0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1,
|
||||
0xB8, 0xA8, 0xB2, 0x86,
|
||||
|
||||
# bank 4, 256 bytes
|
||||
0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35,
|
||||
0x3D, 0xB2, 0xB6, 0xBA,
|
||||
0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A,
|
||||
0xB8, 0xAA, 0x87, 0x2C,
|
||||
0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4,
|
||||
0xCD, 0xC9, 0xF1, 0xB8,
|
||||
0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55,
|
||||
0x7D, 0xB5, 0x93, 0xA3,
|
||||
0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97,
|
||||
0x83, 0xA8, 0x11, 0x84,
|
||||
0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64,
|
||||
0x18, 0xD8, 0xF1, 0xA5,
|
||||
0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A,
|
||||
0x40, 0x48, 0xF9, 0xF3,
|
||||
0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18,
|
||||
0x97, 0x82, 0xA8, 0xF1,
|
||||
0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3,
|
||||
0xDE, 0xD8, 0x83, 0xA5,
|
||||
0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1,
|
||||
0x84, 0x92, 0xA2, 0x4D,
|
||||
0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32,
|
||||
0xD8, 0x50, 0x71, 0xD9,
|
||||
0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8,
|
||||
0x78, 0x93, 0xA3, 0x4D,
|
||||
0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32,
|
||||
0xD8, 0x50, 0x71, 0xD9,
|
||||
0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8,
|
||||
0x78, 0xA8, 0x8A, 0x9A,
|
||||
0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98,
|
||||
0xA8, 0xD9, 0x08, 0xD8,
|
||||
0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1,
|
||||
0xAF, 0xC8, 0x97, 0x87,
|
||||
|
||||
# bank 5, 256 bytes
|
||||
0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D,
|
||||
0xF3, 0xD9, 0x2A, 0xD8,
|
||||
0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9,
|
||||
0x61, 0xD8, 0x6C, 0x68,
|
||||
0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3,
|
||||
0x84, 0x19, 0x3D, 0x5D,
|
||||
0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8,
|
||||
0xB0, 0xAF, 0x8F, 0x94,
|
||||
0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8,
|
||||
0x87, 0x9A, 0x35, 0xDA,
|
||||
0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98,
|
||||
0x85, 0x02, 0x2E, 0x56,
|
||||
0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9,
|
||||
0x28, 0xD8, 0x4D, 0xD9,
|
||||
0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8,
|
||||
0xA3, 0x29, 0x83, 0xDA,
|
||||
0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8,
|
||||
0xB8, 0xB0, 0xA8, 0x8A,
|
||||
0x9A, 0xF5, 0x20, 0xAA, 0xDA, 0xDF, 0xD8, 0xA8, 0x40, 0xAA, 0xD0, 0xDA,
|
||||
0xDE, 0xD8, 0xA8, 0x60,
|
||||
0xAA, 0xDA, 0xD0, 0xDF, 0xD8, 0xF1, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06,
|
||||
0x99, 0x07, 0xAB, 0x97,
|
||||
0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, 0xB8, 0xB0, 0xB4, 0xA8,
|
||||
0x8C, 0x9C, 0xF0, 0x04,
|
||||
0x28, 0x51, 0x79, 0x1D, 0x30, 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98,
|
||||
0x2C, 0x50, 0x50, 0x78,
|
||||
0x78, 0x9B, 0xF1, 0x1A, 0xB0, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79,
|
||||
0x8B, 0x29, 0x51, 0x79,
|
||||
0x8A, 0x24, 0x70, 0x59, 0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38,
|
||||
0x8B, 0x39, 0x40, 0x68,
|
||||
0x8A, 0x64, 0x48, 0x31, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09,
|
||||
0x71, 0x58, 0x44, 0x68,
|
||||
|
||||
# bank 6, 256 bytes
|
||||
0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C,
|
||||
0xF0, 0x8C, 0xA8, 0x04,
|
||||
0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C,
|
||||
0x02, 0x26, 0x46, 0x66,
|
||||
0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69,
|
||||
0x38, 0x64, 0x48, 0x31,
|
||||
0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8,
|
||||
0x19, 0x31, 0x48, 0x60,
|
||||
0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19,
|
||||
0x86, 0xA8, 0x6E, 0x76,
|
||||
0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22,
|
||||
0x8A, 0x6E, 0x8A, 0x56,
|
||||
0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E,
|
||||
0x6E, 0x9D, 0xB8, 0xAD,
|
||||
0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D,
|
||||
0x55, 0x7D, 0x81, 0x91,
|
||||
0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8,
|
||||
0x4D, 0xD9, 0x48, 0xD8,
|
||||
0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8,
|
||||
0x51, 0xD9, 0x04, 0xAE,
|
||||
0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE,
|
||||
0x19, 0x81, 0xAD, 0xD9,
|
||||
0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7,
|
||||
0xD9, 0xAD, 0xAD, 0xAD,
|
||||
0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E,
|
||||
0x76, 0xF3, 0xAC, 0x2E,
|
||||
0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C,
|
||||
0xAC, 0x30, 0x18, 0xA8,
|
||||
0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C,
|
||||
0x24, 0xF2, 0xB0, 0x89,
|
||||
0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51,
|
||||
0xD9, 0xD8, 0xD8, 0x79,
|
||||
|
||||
# bank 7, 138 bytes (remainder)
|
||||
0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91,
|
||||
0x2D, 0xD9, 0x28, 0xD8,
|
||||
0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35,
|
||||
0x3D, 0x80, 0x25, 0xDA,
|
||||
0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28,
|
||||
0x34, 0x3C, 0xF3, 0xAB,
|
||||
0x8B, 0xF8, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xFA, 0xB0,
|
||||
0x87, 0x9C, 0xB9, 0xA3,
|
||||
0xDD, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x95, 0xF1, 0xA3, 0xA3, 0xA3, 0x9D,
|
||||
0xF1, 0xA3, 0xA3, 0xA3,
|
||||
0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
|
||||
0xA3, 0xA3, 0xA3, 0xA3,
|
||||
0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99,
|
||||
0xF1, 0xA3, 0xA3, 0xA3,
|
||||
0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3,
|
||||
0x9B, 0xA3, 0xA3, 0xDC,
|
||||
0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF]
|
||||
|
||||
# dmpConfig has size MPU6050_DMP_CONFIG_SIZE = 192
|
||||
dmpConfig = [
|
||||
# BANK OFFSET LENGTH [DATA]
|
||||
0x03, 0x7B, 0x03, 0x4C, 0xCD, 0x6C, # FCFG_1 inv_set_gyro_calibration
|
||||
0x03, 0xAB, 0x03, 0x36, 0x56, 0x76, # FCFG_3 inv_set_gyro_calibration
|
||||
0x00, 0x68, 0x04, 0x02, 0xCB, 0x47, 0xA2,
|
||||
# D_0_104 inv_set_gyro_calibration
|
||||
0x02, 0x18, 0x04, 0x00, 0x05, 0x8B, 0xC1,
|
||||
# D_0_24 inv_set_gyro_calibration
|
||||
0x01, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00,
|
||||
# D_1_152 inv_set_accel_calibration
|
||||
0x03, 0x7F, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97,
|
||||
# FCFG_2 inv_set_accel_calibration
|
||||
0x03, 0x89, 0x03, 0x26, 0x46, 0x66, # FCFG_7 inv_set_accel_calibration
|
||||
0x00, 0x6C, 0x02, 0x20, 0x00, # D_0_108 inv_set_accel_calibration
|
||||
0x02, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00,
|
||||
# CPASS_MTX_00 inv_set_compass_calibration
|
||||
0x02, 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, # CPASS_MTX_01
|
||||
0x02, 0x48, 0x04, 0x00, 0x00, 0x00, 0x00, # CPASS_MTX_02
|
||||
0x02, 0x4C, 0x04, 0x00, 0x00, 0x00, 0x00, # CPASS_MTX_10
|
||||
0x02, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, # CPASS_MTX_11
|
||||
0x02, 0x54, 0x04, 0x00, 0x00, 0x00, 0x00, # CPASS_MTX_12
|
||||
0x02, 0x58, 0x04, 0x00, 0x00, 0x00, 0x00, # CPASS_MTX_20
|
||||
0x02, 0x5C, 0x04, 0x00, 0x00, 0x00, 0x00, # CPASS_MTX_21
|
||||
0x02, 0xBC, 0x04, 0x00, 0x00, 0x00, 0x00, # CPASS_MTX_22
|
||||
0x01, 0xEC, 0x04, 0x00, 0x00, 0x40, 0x00,
|
||||
# D_1_236 inv_apply_endian_accel
|
||||
0x03, 0x7F, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97,
|
||||
# FCFG_2 inv_set_mpu_sensors
|
||||
0x04, 0x02, 0x03, 0x0D, 0x35, 0x5D,
|
||||
# CFG_MOTION_BIAS inv_turn_on_bias_from_no_motion
|
||||
0x04, 0x09, 0x04, 0x87, 0x2D, 0x35, 0x3D, # FCFG_5 inv_set_bias_update
|
||||
0x00, 0xA3, 0x01, 0x00, # D_0_163 inv_set_dead_zone
|
||||
# SPECIAL 0x01 = enable interrupts
|
||||
0x00, 0x00, 0x00, 0x01, # SET INT_ENABLE at i=22, SPECIAL INSTRUCTION
|
||||
0x07, 0x86, 0x01, 0xFE, # CFG_6 inv_set_fifo_interupt
|
||||
0x07, 0x41, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38,
|
||||
# CFG_8 inv_send_quaternion
|
||||
0x07, 0x7E, 0x01, 0x30, # CFG_16 inv_set_footer
|
||||
0x07, 0x46, 0x01, 0x9A, # CFG_GYRO_SOURCE inv_send_gyro
|
||||
0x07, 0x47, 0x04, 0xF1, 0x28, 0x30, 0x38,
|
||||
# CFG_9 inv_send_gyro -> inv_construct3_fifo
|
||||
0x07, 0x6C, 0x04, 0xF1, 0x28, 0x30, 0x38,
|
||||
# CFG_12 inv_send_accel -> inv_construct3_fifo
|
||||
0x02, 0x16, 0x02, 0x00, 0x01] # D_0_22 inv_set_fifo_rate
|
||||
|
||||
# This very last 0x01 WAS a 0x09, which drops the FIFO rate down to 20 Hz.
|
||||
# 0x07 is 25 Hz, 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends
|
||||
# to result in very noisy data. DMP output frequency is calculated easily
|
||||
# using this equation: (200Hz / (1 + value))
|
||||
|
||||
# It is important to make sure the host processor can keep up with reading
|
||||
# and processing the FIFO output at the desired rate. Handling FIFO overflow
|
||||
# cleanly is also a good idea.
|
||||
|
||||
# dmpUpdates has size MPU6050_DMP_UPDATES_SIZE = 47
|
||||
dmpUpdates = [
|
||||
0x01, 0xB2, 0x02, 0xFF, 0xFF,
|
||||
0x01, 0x90, 0x04, 0x09, 0x23, 0xA1, 0x35,
|
||||
0x01, 0x6A, 0x02, 0x06, 0x00,
|
||||
0x01, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x60, 0x04, 0x40, 0x00, 0x00, 0x00,
|
||||
0x01, 0x62, 0x02, 0x00, 0x00,
|
||||
0x00, 0x60, 0x04, 0x00, 0x40, 0x00, 0x00]
|
||||
@@ -0,0 +1,135 @@
|
||||
__author__ = 'Geir Istad'
|
||||
"""
|
||||
MPU6050 Python I2C Class
|
||||
Copyright (c) 2015 Geir Istad
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
Code based on
|
||||
I2Cdev library collection - 3D math helper
|
||||
by Jeff Rowberg <jeff@rowberg.net>
|
||||
============================================
|
||||
I2Cdev device library code is placed under the MIT license
|
||||
Copyright (c) 2012 Jeff Rowberg
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
===============================================
|
||||
"""
|
||||
from math import sqrt
|
||||
|
||||
|
||||
class Quaternion:
|
||||
w = 0.0
|
||||
x = 0.0
|
||||
y = 0.0
|
||||
z = 0.0
|
||||
|
||||
def __init__(self, a_w=1.0, a_x=0.0, a_y=0.0, a_z=0.0):
|
||||
self.w = a_w
|
||||
self.x = a_x
|
||||
self.y = a_y
|
||||
self.z = a_z
|
||||
|
||||
def get_product(self, a_quat):
|
||||
result = Quaternion(
|
||||
self.w * a_quat.w - self.x * a_quat.x -
|
||||
self.y * a_quat.y - self.z * a_quat.z,
|
||||
|
||||
self.w * a_quat.x + self.x * a_quat.w +
|
||||
self.y * a_quat.z - self.z * a_quat.y,
|
||||
|
||||
self.w * a_quat.y - self.x * a_quat.z +
|
||||
self.y * a_quat.w + self.z * a_quat.x,
|
||||
|
||||
self.w * a_quat.z + self.x * a_quat.y -
|
||||
self.y * a_quat.x + self.z * a_quat.w)
|
||||
return result
|
||||
|
||||
def get_conjugate(self):
|
||||
result = Quaternion(self.w, -self.x, -self.y, -self.z)
|
||||
return result
|
||||
|
||||
def get_magnitude(self):
|
||||
return sqrt(self.w * self.w + self.x * self.x + self.y * self.y +
|
||||
self.z * self.z)
|
||||
|
||||
def normalize(self):
|
||||
m = self.get_magnitude()
|
||||
self.w = self.w / m
|
||||
self.x = self.x / m
|
||||
self.y = self.y / m
|
||||
self.z = self.z / m
|
||||
|
||||
def get_normalized(self):
|
||||
result = Quaternion(self.w, self.x, self.y, self.z)
|
||||
result.normalize()
|
||||
return result
|
||||
|
||||
|
||||
class XYZVector:
|
||||
x = 0.0
|
||||
y = 0.0
|
||||
z = 0.0
|
||||
|
||||
def __init__(self, a_x=0.0, a_y=0.0, a_z=0.0):
|
||||
self.x = a_x
|
||||
self.y = a_y
|
||||
self.z = a_z
|
||||
|
||||
def get_magnitude(self):
|
||||
return sqrt(self.x*self.x + self.y*self.y + self.z*self.z)
|
||||
|
||||
def normalize(self):
|
||||
m = self.get_magnitude()
|
||||
self.x = self.x / m
|
||||
self.y = self.y / m
|
||||
self.z = self.z / m
|
||||
|
||||
def get_normalized(self):
|
||||
result = XYZVector(self.x, self.y, self.z)
|
||||
result.normalize()
|
||||
return result
|
||||
|
||||
def rotate(self, a_quat):
|
||||
p = Quaternion(0.0, self.x, self.y, self.z)
|
||||
p = a_quat.get_product(p)
|
||||
p = p.get_product(a_quat.get_conjugate())
|
||||
# By magic quaternion p is now [0, x', y', z']
|
||||
self.x = p.x
|
||||
self.y = p.y
|
||||
self.z = p.z
|
||||
|
||||
def get_rotated(self, a_quat):
|
||||
r = XYZVector(self.x, self.y, self.z)
|
||||
r.rotate(a_quat)
|
||||
return r
|
||||
@@ -0,0 +1,68 @@
|
||||
from gpiozero import LED
|
||||
import os
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
|
||||
host_name = '192.168.1.147' # Change this to your Raspberry Pi IP address
|
||||
host_port = 8000
|
||||
led = LED(17) # define LED pin according to BCM Numbering
|
||||
|
||||
class MyServer(BaseHTTPRequestHandler):
|
||||
""" A special implementation of BaseHTTPRequestHander for reading data from
|
||||
and control GPIO of a Raspberry Pi
|
||||
"""
|
||||
def do_HEAD(self):
|
||||
""" do_HEAD() can be tested use curl command
|
||||
'curl -I http://server-ip-address:port'
|
||||
"""
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', 'text/html')
|
||||
self.end_headers()
|
||||
def _redirect(self, path):
|
||||
self.send_response(303)
|
||||
self.send_header('Content-type', 'text/html')
|
||||
self.send_header('Location', path)
|
||||
self.end_headers()
|
||||
def do_GET(self):
|
||||
""" do_GET() can be tested using curl command
|
||||
'curl http://server-ip-address:port'
|
||||
"""
|
||||
html = '''
|
||||
<html>
|
||||
<body style="width:960px; margin: 20px auto;">
|
||||
<h1>Welcome to my Raspberry Pi</h1>
|
||||
<p>Current GPU temperature is {}</p>
|
||||
<form action="/" method="POST">
|
||||
Turn LED :
|
||||
<input type="submit" name="submit" value="On">
|
||||
<input type="submit" name="submit" value="Off">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
temp = os.popen("vcgencmd measure_temp").read()
|
||||
# temp = os.popen("/opt/vc/bin/vcgencmd measure_temp").read()
|
||||
self.do_HEAD()
|
||||
self.wfile.write(html.format(temp[5:]).encode("utf-8"))
|
||||
def do_POST(self):
|
||||
""" do_POST() can be tested using curl command
|
||||
'curl -d "submit=On" http://server-ip-address:port'
|
||||
"""
|
||||
content_length = int(self.headers['Content-Length']) # Get the size of data
|
||||
post_data = self.rfile.read(content_length).decode("utf-8") # Get the data
|
||||
post_data = post_data.split("=")[1] # Only keep the value
|
||||
|
||||
if post_data == 'On':
|
||||
led.on()
|
||||
else:
|
||||
led.off()
|
||||
print("LED is {}".format(post_data))
|
||||
self._redirect('/') # Redirect back to the root url
|
||||
|
||||
if __name__ == '__main__':
|
||||
http_server = HTTPServer((host_name, host_port), MyServer)
|
||||
print("Server Starts - %s:%s" % (host_name, host_port))
|
||||
try:
|
||||
http_server.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
http_server.server_close()
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python3
|
||||
#############################################################################
|
||||
# Filename : LightWater03.py
|
||||
# Description : Control LED with 74HC595 on the DIY circuit board
|
||||
# auther : www.freenove.com
|
||||
# modification: 2023/05/15
|
||||
########################################################################
|
||||
from gpiozero import OutputDevice
|
||||
import time
|
||||
|
||||
LSBFIRST = 1
|
||||
MSBFIRST = 2
|
||||
|
||||
# define the pins for 74HC595
|
||||
dataPin = OutputDevice(17) # DS Pin of 74HC595(Pin14)
|
||||
latchPin = OutputDevice(27) # ST_CP Pin of 74HC595(Pin12)
|
||||
clockPin = OutputDevice(22) # CH_CP Pin of 74HC595(Pin11)
|
||||
|
||||
# Define an array to store the pulse width of LED
|
||||
pluseWidth = [0,0,0,0,0,0,0,0,64,32,16,8,4,2,1,0,0,0,0,0,0,0,0]
|
||||
|
||||
# shiftOut function, use bit serial transmission.
|
||||
def shiftOut(order,val):
|
||||
for i in range(0,8):
|
||||
clockPin.off()
|
||||
if(order == LSBFIRST):
|
||||
dataPin.on() if (0x01&(val>>i)==0x01) else dataPin.off()
|
||||
elif(order == MSBFIRST):
|
||||
dataPin.on() if (0x80&(val<<i)==0x80) else dataPin.off()
|
||||
clockPin.on()
|
||||
|
||||
def outData(data):
|
||||
latchPin.off()
|
||||
shiftOut(LSBFIRST,data)
|
||||
latchPin.on()
|
||||
|
||||
def loop():
|
||||
moveSpeed = 0.1 # moveSpeed works like a relay, the larger, the slower
|
||||
index = 0 # array index starts from 0
|
||||
lastMove = time.time() # record the start time
|
||||
while True:
|
||||
if(time.time() - lastMove > moveSpeed): # control speed
|
||||
lastMove = time.time() # Record the time point of the move
|
||||
index +=1 # move to next
|
||||
if(index > 15): # index to 0
|
||||
index = 0
|
||||
|
||||
for i in range(0,64): # The cycle of PWM is 64 cycles
|
||||
data = 0
|
||||
for j in range(0,8): #Calculate the output state of this loop
|
||||
if(i < pluseWidth[j+index]): #Calculate the LED state according to the pulse width
|
||||
data |= 1<<j # Calculate the data
|
||||
outData(data) # Send the data to 74HC595
|
||||
|
||||
def destroy():
|
||||
dataPin.close()
|
||||
latchPin.close()
|
||||
clockPin.close()
|
||||
|
||||
if __name__ == '__main__': # Program entrance
|
||||
print ('Program is starting...')
|
||||
try:
|
||||
loop()
|
||||
except KeyboardInterrupt: # Press ctrl-c to end the program.
|
||||
destroy()
|
||||
print("Ending program")
|
||||
Reference in New Issue
Block a user