Update
@@ -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")
|
||||
@@ -10,7 +10,8 @@ class ADCDevice {
|
||||
public int cmd = 0;
|
||||
public I2C i2c;
|
||||
public ADCDevice() {
|
||||
i2c = new I2C(I2C.list()[0]);
|
||||
//Note that if you are running on a version 1 Raspberry Pi, you need to change the subscript index to 0.
|
||||
i2c = new I2C(I2C.list()[1]);
|
||||
}
|
||||
|
||||
public boolean detectI2C(int addr) {
|
||||
|
||||
@@ -10,7 +10,8 @@ class ADCDevice {
|
||||
public int cmd = 0;
|
||||
public I2C i2c;
|
||||
public ADCDevice() {
|
||||
i2c = new I2C(I2C.list()[0]);
|
||||
//Note that if you are running on a version 1 Raspberry Pi, you need to change the subscript index to 0.
|
||||
i2c = new I2C(I2C.list()[1]);
|
||||
}
|
||||
|
||||
public boolean detectI2C(int addr) {
|
||||
|
||||
@@ -10,7 +10,8 @@ class ADCDevice {
|
||||
public int cmd = 0;
|
||||
public I2C i2c;
|
||||
public ADCDevice() {
|
||||
i2c = new I2C(I2C.list()[0]);
|
||||
//Note that if you are running on a version 1 Raspberry Pi, you need to change the subscript index to 0.
|
||||
i2c = new I2C(I2C.list()[1]);
|
||||
}
|
||||
|
||||
public boolean detectI2C(int addr) {
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0"?>
|
||||
<project name="Processing Hardware I/O Library" default="build">
|
||||
|
||||
<target name="clean" description="Clean the build directories">
|
||||
<delete dir="bin" />
|
||||
<delete file="library/io.jar" />
|
||||
</target>
|
||||
|
||||
<target name="compile" description="Compile sources">
|
||||
<condition property="core-built">
|
||||
<available file="../../../core/library/core.jar" />
|
||||
</condition>
|
||||
<fail unless="core-built" message="Please build the core library first and make sure it sits in ../../../core/library/core.jar" />
|
||||
|
||||
<mkdir dir="bin" />
|
||||
<javac source="1.8"
|
||||
target="1.8"
|
||||
srcdir="src" destdir="bin"
|
||||
encoding="UTF-8"
|
||||
includeAntRuntime="false"
|
||||
classpath="../../../core/library/core.jar"
|
||||
nowarn="true"
|
||||
compiler="org.eclipse.jdt.core.JDTCompilerAdapter">
|
||||
<compilerclasspath path="../../mode/org.eclipse.jdt.core.jar;
|
||||
../../mode/jdtCompilerAdapter.jar" />
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<target name="build" depends="compile" description="Build I/O library">
|
||||
<jar basedir="bin" destfile="library/io.jar" />
|
||||
</target>
|
||||
|
||||
<target name="dist" depends="build" description="Package standalone library">
|
||||
<!-- set revision number as library version -->
|
||||
<loadfile srcfile="../../../todo.txt" property="revision">
|
||||
<filterchain>
|
||||
<headfilter lines="1"/>
|
||||
<tokenfilter>
|
||||
<stringtokenizer suppressdelims="true"/>
|
||||
<!-- grab the thing from the first line that's 4 digits -->
|
||||
<containsregex pattern="(\d\d\d\d)" />
|
||||
</tokenfilter>
|
||||
</filterchain>
|
||||
</loadfile>
|
||||
<replaceregexp file="library.properties" match="version = .*" replace="version = ${revision}" flags="g" />
|
||||
<replaceregexp file="library.properties" match="prettyVersion = .*" replace="prettyVersion = ${revision}" flags="g" />
|
||||
|
||||
<get src="http://download.processing.org/reference.zip"
|
||||
dest="reference.zip"
|
||||
usetimestamp="true" />
|
||||
<mkdir dir="reference" />
|
||||
<unzip dest="."
|
||||
src="reference.zip"
|
||||
overwrite="true">
|
||||
<patternset>
|
||||
<include name="reference/css/**" />
|
||||
<include name="reference/img/**" />
|
||||
<include name="reference/javascript/**" />
|
||||
<include name="reference/libraries/io/**" />
|
||||
</patternset>
|
||||
</unzip>
|
||||
<delete file="reference.zip" />
|
||||
<echo file="reference/index.html" message="<html><head><meta http-equiv='refresh' content='0; url=libraries/io/index.html'></head><body></body></html>" />
|
||||
|
||||
<zip destfile="../io.zip">
|
||||
<zipfileset dir="." prefix="io">
|
||||
<exclude name="bin/**"/>
|
||||
</zipfileset>
|
||||
</zip>
|
||||
|
||||
<copy file="library.properties"
|
||||
toFile="../io.txt"/>
|
||||
</target>
|
||||
</project>
|
||||
@@ -0,0 +1,107 @@
|
||||
import processing.io.I2C;
|
||||
|
||||
// ADS1015 and ADS1115 are Analog-to-Digital converters using I2C
|
||||
// they have four channels and 12 and 16 bits of resolution respectively
|
||||
// datasheets: http://www.ti.com/lit/ds/symlink/ads1015.pdf
|
||||
// http://www.ti.com/lit/ds/symlink/ads1115.pdf
|
||||
|
||||
class ADS1015 extends ADS1X15 {
|
||||
ADS1015(String dev, int address) {
|
||||
super(dev, address);
|
||||
bitShift = 4;
|
||||
conversionDelay = 1;
|
||||
}
|
||||
|
||||
// returns a number between -1.0 and 1.0
|
||||
float analogRead(int channel) {
|
||||
return readSingleEnded(channel) / 2047.0;
|
||||
}
|
||||
}
|
||||
|
||||
class ADS1115 extends ADS1X15 {
|
||||
ADS1115(String dev, int address) {
|
||||
super(dev, address);
|
||||
bitShift = 0;
|
||||
conversionDelay = 8;
|
||||
}
|
||||
|
||||
// returns a number between -1.0 and 1.0
|
||||
float analogRead(int channel) {
|
||||
return readSingleEnded(channel) / 32767.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ADS1X15 extends I2C {
|
||||
int address;
|
||||
int bitShift; // bits to shift the result to the right
|
||||
int conversionDelay; // in ms
|
||||
int channel; // last channel used
|
||||
int range; // see below
|
||||
|
||||
// possible voltage ranges
|
||||
static final int INTERNAL_6V144 = 0; // +/- 6.144V
|
||||
static final int INTERNAL_4V096 = 1; // +/- 4.096V (library default)
|
||||
static final int INTERNAL_2V048 = 2; // +/- 2.048V
|
||||
static final int INTERNAL_1V024 = 3; // +/- 1.024V
|
||||
static final int INTERNAL_0V512 = 4; // +/- 0.512V
|
||||
static final int INTERNAL_0V256 = 5; // +/- 0.256V
|
||||
|
||||
ADS1X15(String dev, int address) {
|
||||
super(dev);
|
||||
this.address = address;
|
||||
this.channel = -1;
|
||||
this.range = INTERNAL_4V096;
|
||||
}
|
||||
|
||||
// be careful not to make the input voltage exceed VCC + 0.3V
|
||||
// this is regardless of the selected input range
|
||||
void analogReference(int type) {
|
||||
if (type < 0 || 7 < type) {
|
||||
throw new RuntimeException("Invalid range setting");
|
||||
}
|
||||
range = type;
|
||||
}
|
||||
|
||||
int readSingleEnded(int channel) {
|
||||
if (channel < 0 || 3 < channel) {
|
||||
System.err.println("The channel needs to be from 0 to 3");
|
||||
throw new IllegalArgumentException("Unexpected channel");
|
||||
}
|
||||
|
||||
if (channel != this.channel) {
|
||||
int config = 0x0183; // start with the default value from datasheet
|
||||
config &= ~0x100; // enable continuous readings
|
||||
config |= (range << 9); // set selected range (gain)
|
||||
config |= (1 << 14) | (channel << 12); // set single-ended and channel
|
||||
config |= (1 << 15); // start a single conversion
|
||||
writeRegister(0x01, config); // write to the configuration register at 0x01
|
||||
|
||||
// when the channel switched we need to wait for the upcoming
|
||||
// conversion to finish
|
||||
delay(conversionDelay);
|
||||
|
||||
// save the channel so that we don't need to do the same for
|
||||
// subsequent reads from the same channel
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
return readS16(0x00) >> bitShift; // read from the conversion register at 0x00
|
||||
// the ADS1015 will have its 12-bit result in the upper bits, shift those right by four
|
||||
}
|
||||
|
||||
protected void writeRegister(int register, int value) {
|
||||
beginTransmission(address);
|
||||
write(register);
|
||||
write(value >> 8);
|
||||
write(value & 0xFF);
|
||||
endTransmission();
|
||||
}
|
||||
|
||||
protected int readS16(int register) {
|
||||
beginTransmission(address);
|
||||
write(register);
|
||||
byte[] in = read(2);
|
||||
return (in[0] << 8) | in[1];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import processing.io.*;
|
||||
ADS1015 adc;
|
||||
// or, alternatively:
|
||||
// ADS1115 adc;
|
||||
|
||||
// see setup.png in the sketch folder for wiring details
|
||||
|
||||
void setup() {
|
||||
//printArray(I2C.list());
|
||||
|
||||
adc = new ADS1015("i2c-1", 0x48);
|
||||
//adc = new ADS1115("i2c-1", 0x48);
|
||||
|
||||
// this sets the measuring range to +/- 4.096 Volts
|
||||
// other ranges supported by this chip:
|
||||
// INTERNAL_6V144, INTERNAL_2V048, INTERNAL_1V024,
|
||||
// INTERNAL_0V512, INTERNAL_0V256
|
||||
adc.analogReference(ADS1X15.INTERNAL_4V096);
|
||||
|
||||
// Important: do not attempt to measure voltages higher than
|
||||
// the supply voltage (VCC) + 0.3V, meaning that 3.6V is the
|
||||
// absolut maximum voltage on the Raspberry Pi. This is
|
||||
// irrespective of the analogReference() setting above.
|
||||
}
|
||||
|
||||
void draw() {
|
||||
// this will return a number between 0 and 1
|
||||
// (as long as your voltage is positive)
|
||||
float measured = adc.analogRead(0);
|
||||
|
||||
// multiply with the selected range to get the absolut voltage
|
||||
float volts = measured * 4.096;
|
||||
println("Analog Input 0 is " + volts + "V");
|
||||
|
||||
background(255);
|
||||
fill(measured * 255);
|
||||
ellipse(width/2, height/2, width * 0.75, width * 0.75);
|
||||
}
|
||||
|
After Width: | Height: | Size: 83 KiB |
@@ -0,0 +1,20 @@
|
||||
import processing.io.*;
|
||||
MCP3001 adc;
|
||||
|
||||
// see setup.png in the sketch folder for wiring details
|
||||
|
||||
void setup() {
|
||||
//printArray(SPI.list());
|
||||
adc = new MCP3001(SPI.list()[0]);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
// this will return a number between 0 and 1
|
||||
float measured = adc.analogRead();
|
||||
|
||||
// multiply with the supply voltage to get an absolute value
|
||||
float volts = 3.3 * measured;
|
||||
println("Analog Input is " + volts + "V");
|
||||
|
||||
background(measured * 255);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import processing.io.SPI;
|
||||
|
||||
// MCP3001 is a Analog-to-Digital converter using SPI
|
||||
// datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf
|
||||
|
||||
class MCP3001 extends SPI {
|
||||
|
||||
MCP3001(String dev) {
|
||||
super(dev);
|
||||
settings(500000, SPI.MSBFIRST, SPI.MODE0);
|
||||
}
|
||||
|
||||
// returns a number between 0.0 and 1.0
|
||||
float analogRead() {
|
||||
// dummy write, actual values don't matter
|
||||
byte[] out = { 0, 0 };
|
||||
byte[] in = transfer(out);
|
||||
// some input bit shifting according to the datasheet p. 16
|
||||
int val = ((in[0] & 0x1f) << 5) | ((in[1] & 0xf8) >> 3);
|
||||
// val is between 0 and 1023
|
||||
return val/1023.0;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 66 KiB |
@@ -0,0 +1,22 @@
|
||||
import processing.io.*;
|
||||
MCP3008 adc;
|
||||
|
||||
// see setup.png in the sketch folder for wiring details
|
||||
|
||||
void setup() {
|
||||
//printArray(SPI.list());
|
||||
adc = new MCP3008(SPI.list()[0]);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
// this will return a number between 0 and 1
|
||||
float measured = adc.analogRead(0);
|
||||
|
||||
// multiply with the supply voltage to get an absolute value
|
||||
float volts = 3.3 * measured;
|
||||
println("Analog Input 0 is " + volts + "V");
|
||||
|
||||
background(255);
|
||||
fill(measured * 255);
|
||||
ellipse(width/2, height/2, width * 0.75, width * 0.75);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import processing.io.SPI;
|
||||
|
||||
// MCP3008 is a Analog-to-Digital converter using SPI
|
||||
// other than the MCP3001, this has 8 input channels
|
||||
// datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf
|
||||
|
||||
class MCP3008 extends SPI {
|
||||
|
||||
MCP3008(String dev) {
|
||||
super(dev);
|
||||
settings(500000, SPI.MSBFIRST, SPI.MODE0);
|
||||
}
|
||||
|
||||
// returns a number between 0.0 and 1.0
|
||||
float analogRead(int channel) {
|
||||
if (channel < 0 || 7 < channel) {
|
||||
System.err.println("The channel needs to be from 0 to 7");
|
||||
throw new IllegalArgumentException("Unexpected channel");
|
||||
}
|
||||
byte[] out = { 0, 0, 0 };
|
||||
// encode the channel number in the first byte
|
||||
out[0] = (byte)(0x18 | channel);
|
||||
byte[] in = transfer(out);
|
||||
int val = ((in[1] & 0x03) << 8) | (in[2] & 0xff);
|
||||
// val is between 0 and 1023
|
||||
return val/1023.0;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 68 KiB |
@@ -0,0 +1,19 @@
|
||||
import processing.io.*;
|
||||
HMC6352 compass;
|
||||
|
||||
// see setup.png in the sketch folder for wiring details
|
||||
|
||||
void setup() {
|
||||
// the module's I2C address can be changed by modifying values in its EEPROM
|
||||
// 0x21 is however the default address
|
||||
|
||||
//printArray(I2C.list());
|
||||
compass = new HMC6352("i2c-1", 0x21);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(255);
|
||||
float deg = compass.heading();
|
||||
println(deg + " degrees");
|
||||
line(width/2, height/2, width/2+sin(radians(deg))*width/2, height/2-cos(radians(deg))*height/2);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import processing.io.I2C;
|
||||
|
||||
// HMC6352 is a digital compass using I2C
|
||||
// datasheet: https://www.sparkfun.com/datasheets/Components/HMC6352.pdf
|
||||
|
||||
class HMC6352 extends I2C {
|
||||
int address;
|
||||
|
||||
HMC6352(String dev, int address) {
|
||||
super(dev);
|
||||
this.address = address;
|
||||
setHeadingMode();
|
||||
}
|
||||
|
||||
void setHeadingMode() {
|
||||
beginTransmission(address);
|
||||
// command byte for writing to EEPROM
|
||||
write(0x77);
|
||||
// address of the output data control byte
|
||||
write(0x4e);
|
||||
// give us the plain heading
|
||||
write(0x00);
|
||||
endTransmission();
|
||||
}
|
||||
|
||||
float heading() {
|
||||
beginTransmission(address);
|
||||
// command byte for reading the data
|
||||
write(0x41);
|
||||
byte[] in = read(2);
|
||||
endTransmission();
|
||||
// put bytes together to tenth of degrees
|
||||
// & 0xff makes sure the byte is not interpreted as a negative value
|
||||
int deg = (in[0] & 0xff) << 8 | (in[1] & 0xff);
|
||||
// return degrees
|
||||
return deg / 10.0;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 194 KiB |
@@ -0,0 +1,12 @@
|
||||
import processing.io.*;
|
||||
MCP4725 dac;
|
||||
|
||||
void setup() {
|
||||
//printArray(I2C.list());
|
||||
dac = new MCP4725(I2C.list()[0], 0x60);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(map(mouseX, 0, width, 0, 255));
|
||||
dac.setAnalog(map(mouseX, 0, width, 0.0, 1.0));
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import processing.io.I2C;
|
||||
|
||||
// MCP4725 is a Digital-to-Analog converter using I2C
|
||||
// datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22039d.pdf
|
||||
|
||||
class MCP4725 extends I2C {
|
||||
int address;
|
||||
|
||||
// there can be more than one device connected to the bus
|
||||
// as long as they have different addresses
|
||||
MCP4725(String dev, int address) {
|
||||
super(dev);
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
// outputs voltages from 0V to the supply voltage
|
||||
// (works with 3.3V and 5V)
|
||||
void setAnalog(float fac) {
|
||||
fac = constrain(fac, 0.0, 1.0);
|
||||
// convert to 12 bit value
|
||||
int val = int(4095 * fac);
|
||||
beginTransmission(address);
|
||||
write(val >> 8);
|
||||
write(val & 255);
|
||||
endTransmission();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import processing.io.*;
|
||||
|
||||
// 0.96" 128x64 OLED display ("SKU 346540")
|
||||
SSD1306 oled;
|
||||
|
||||
void setup() {
|
||||
size(128, 64);
|
||||
|
||||
// the display can be set to one of these two addresses: 0x3c (default) or 0x3d
|
||||
// (they might be listed as 0x7a and 0x7b on the circuit board)
|
||||
|
||||
// you might need to use a different interface on other SBCs
|
||||
oled = new SSD1306("i2c-1", 0x3c);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
stroke(255);
|
||||
line(0, 0, 127, 63);
|
||||
line(0, 63, 127, 0);
|
||||
oled.sendImage(get());
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
import processing.io.I2C;
|
||||
|
||||
// SSD1306 is a small, inexpensive 128x64 pixels monochrome OLED display
|
||||
// available online as "0.96" 128x64 OLED display", SKU 346540
|
||||
// or from Adafruit
|
||||
// datasheet: https://www.adafruit.com/datasheets/SSD1306.pdf
|
||||
|
||||
class SSD1306 extends I2C {
|
||||
int address;
|
||||
|
||||
// there can be more than one device connected to the bus
|
||||
// as long as they have different addresses
|
||||
SSD1306(String dev, int address) {
|
||||
super(dev);
|
||||
this.address = address;
|
||||
init();
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
writeCommand(0xae); // turn display off
|
||||
writeCommand(0xa8, 0x3f); // set multiplex ratio to the highest setting
|
||||
writeCommand(0x8d, 0x14); // enable charge pump
|
||||
writeCommand(0x20, 0x00); // set memory addressing mode to horizontal
|
||||
writeCommand(0xd5, 0x80); // set display clock divide ratio & oscillator frequency to default
|
||||
writeCommand(0xd3, 0x00); // no display offset
|
||||
writeCommand(0x40 | 0x00); // set default display start line
|
||||
|
||||
// use the following two lines to flip the display
|
||||
writeCommand(0xa0 | 0x01); // set segment re-map
|
||||
writeCommand(0xc8); // set COM output scan direction
|
||||
|
||||
writeCommand(0xda, 0x12); // set COM pins hardware configuration
|
||||
writeCommand(0xd9, 0xf1); // set pre-charge period to 241x DCLK
|
||||
writeCommand(0xdB, 0x40); // set VCOMH deselect level
|
||||
writeCommand(0xa4); // display RAM content (not all-on)
|
||||
writeCommand(0xa6); // set normal (not-inverted) display
|
||||
|
||||
// set this since we don't have access to the OLED's reset pins (?)
|
||||
writeCommand(0x21, 0, 127); // set column address
|
||||
writeCommand(0x22, 0, 7); // set page address
|
||||
|
||||
writeCommand(0x81, 0xcf); // set contrast
|
||||
writeCommand(0x2e); // deactivate scroll
|
||||
writeCommand(0xaf); // turn display on
|
||||
}
|
||||
|
||||
void invert(boolean inverted) {
|
||||
if (inverted) {
|
||||
writeCommand(0xa7);
|
||||
} else {
|
||||
writeCommand(0xa6);
|
||||
}
|
||||
}
|
||||
|
||||
void sendImage(PImage img) {
|
||||
sendImage(img, 0, 0);
|
||||
}
|
||||
|
||||
void sendImage(PImage img, int startX, int startY) {
|
||||
byte[] frame = new byte[1024];
|
||||
img.loadPixels();
|
||||
for (int y=startY; y < height && y-startY < 64; y++) {
|
||||
for (int x=startX; x < width && x-startX < 128; x++) {
|
||||
if (128 <= brightness(img.pixels[y*img.width+x])) {
|
||||
// this isn't the normal (scanline) mapping, but 8 pixels below each other at a time
|
||||
// white pixels have their bit turned on
|
||||
frame[x + (y/8)*128] |= (1 << (y % 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
sendFramebuffer(frame);
|
||||
}
|
||||
|
||||
void sendFramebuffer(byte[] buf) {
|
||||
if (buf.length != 1024) {
|
||||
System.err.println("The framebuffer should be 1024 bytes long, with one bit per pixel");
|
||||
throw new IllegalArgumentException("Unexpected buffer size");
|
||||
}
|
||||
|
||||
writeCommand(0x00 | 0x0); // set start address
|
||||
writeCommand(0x10 | 0x0); // set higher column start address
|
||||
writeCommand(0x40 | 0x0); // set start line
|
||||
|
||||
// send the frame buffer as 16 byte long packets
|
||||
for (int i=0; i < buf.length/16; i++) {
|
||||
super.beginTransmission(address);
|
||||
super.write(0x40); // indicates data write
|
||||
for (int j=0; j < 16; j++) {
|
||||
super.write(buf[i*16+j]);
|
||||
}
|
||||
super.endTransmission();
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeCommand(int arg1) {
|
||||
super.beginTransmission(address);
|
||||
super.write(0x00); // indicates command write
|
||||
super.write(arg1);
|
||||
super.endTransmission();
|
||||
}
|
||||
|
||||
protected void writeCommand(int arg1, int arg2) {
|
||||
super.beginTransmission(address);
|
||||
super.write(0x00);
|
||||
super.write(arg1);
|
||||
super.write(arg2);
|
||||
super.endTransmission();
|
||||
}
|
||||
|
||||
protected void writeCommand(int arg1, int arg2, int arg3) {
|
||||
super.beginTransmission(address);
|
||||
super.write(0x00);
|
||||
super.write(arg1);
|
||||
super.write(arg2);
|
||||
super.write(arg3);
|
||||
super.endTransmission();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,407 @@
|
||||
import processing.io.I2C;
|
||||
|
||||
// BME280 is an integrated environmental sensor
|
||||
// It can measure temperature, pressure and humidity
|
||||
// datasheet: https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdf
|
||||
// code contributed by @OlivierLD
|
||||
|
||||
public class BME280 extends I2C {
|
||||
|
||||
public final static int BME280_I2CADDR = 0x77; // this is the default I2C address
|
||||
public final static int DEFAULT_ADDR = BME280_I2CADDR;
|
||||
|
||||
// Operating Modes
|
||||
public final static int BME280_OSAMPLE_1 = 1;
|
||||
public final static int BME280_OSAMPLE_2 = 2;
|
||||
public final static int BME280_OSAMPLE_4 = 3;
|
||||
public final static int BME280_OSAMPLE_8 = 4;
|
||||
public final static int BME280_OSAMPLE_16 = 5;
|
||||
|
||||
// BME280 Registers
|
||||
public final static int BME280_REGISTER_DIG_T1 = 0x88; // Trimming parameter registers
|
||||
public final static int BME280_REGISTER_DIG_T2 = 0x8A;
|
||||
public final static int BME280_REGISTER_DIG_T3 = 0x8C;
|
||||
|
||||
public final static int BME280_REGISTER_DIG_P1 = 0x8E;
|
||||
public final static int BME280_REGISTER_DIG_P2 = 0x90;
|
||||
public final static int BME280_REGISTER_DIG_P3 = 0x92;
|
||||
public final static int BME280_REGISTER_DIG_P4 = 0x94;
|
||||
public final static int BME280_REGISTER_DIG_P5 = 0x96;
|
||||
public final static int BME280_REGISTER_DIG_P6 = 0x98;
|
||||
public final static int BME280_REGISTER_DIG_P7 = 0x9A;
|
||||
public final static int BME280_REGISTER_DIG_P8 = 0x9C;
|
||||
public final static int BME280_REGISTER_DIG_P9 = 0x9E;
|
||||
|
||||
public final static int BME280_REGISTER_DIG_H1 = 0xA1;
|
||||
public final static int BME280_REGISTER_DIG_H2 = 0xE1;
|
||||
public final static int BME280_REGISTER_DIG_H3 = 0xE3;
|
||||
public final static int BME280_REGISTER_DIG_H4 = 0xE4;
|
||||
public final static int BME280_REGISTER_DIG_H5 = 0xE5;
|
||||
public final static int BME280_REGISTER_DIG_H6 = 0xE6;
|
||||
public final static int BME280_REGISTER_DIG_H7 = 0xE7;
|
||||
|
||||
public final static int BME280_REGISTER_CHIPID = 0xD0;
|
||||
public final static int BME280_REGISTER_VERSION = 0xD1;
|
||||
public final static int BME280_REGISTER_SOFTRESET = 0xE0;
|
||||
|
||||
public final static int BME280_REGISTER_CONTROL_HUM = 0xF2;
|
||||
public final static int BME280_REGISTER_CONTROL = 0xF4;
|
||||
public final static int BME280_REGISTER_CONFIG = 0xF5;
|
||||
public final static int BME280_REGISTER_PRESSURE_DATA = 0xF7;
|
||||
public final static int BME280_REGISTER_TEMP_DATA = 0xFA;
|
||||
public final static int BME280_REGISTER_HUMIDITY_DATA = 0xFD;
|
||||
|
||||
private int dig_T1 = 0;
|
||||
private int dig_T2 = 0;
|
||||
private int dig_T3 = 0;
|
||||
|
||||
private int dig_P1 = 0;
|
||||
private int dig_P2 = 0;
|
||||
private int dig_P3 = 0;
|
||||
private int dig_P4 = 0;
|
||||
private int dig_P5 = 0;
|
||||
private int dig_P6 = 0;
|
||||
private int dig_P7 = 0;
|
||||
private int dig_P8 = 0;
|
||||
private int dig_P9 = 0;
|
||||
|
||||
private int dig_H1 = 0;
|
||||
private int dig_H2 = 0;
|
||||
private int dig_H3 = 0;
|
||||
private int dig_H4 = 0;
|
||||
private int dig_H5 = 0;
|
||||
private int dig_H6 = 0;
|
||||
|
||||
private float tFine = 0.0f;
|
||||
|
||||
private int address;
|
||||
private int mode = BME280_OSAMPLE_8;
|
||||
private float standardSeaLevelPressure = 101325.0f; // in Pa (1013.25 hPa)
|
||||
|
||||
protected float temp = 0.0f; // most recent sensor readings, set by update()
|
||||
protected float press = 0.0f;
|
||||
protected float hum = 0.0f;
|
||||
|
||||
|
||||
public BME280(String dev) {
|
||||
this(dev, DEFAULT_ADDR);
|
||||
}
|
||||
|
||||
public BME280(String dev, int address) {
|
||||
super(dev);
|
||||
this.address = address;
|
||||
|
||||
// Soft reset
|
||||
command(BME280_REGISTER_SOFTRESET, (byte)0xB6);
|
||||
// Wait for the chip to wake up
|
||||
delay(300);
|
||||
|
||||
try {
|
||||
readCalibrationData();
|
||||
// showCalibrationData();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
command(BME280_REGISTER_CONTROL, (byte)0x3F);
|
||||
tFine = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read and update all sensors values
|
||||
*/
|
||||
public void update() {
|
||||
// The order used to read the data is important!
|
||||
// 1.temperature, 2.pressure (analog to altitude), 3.humidity.
|
||||
|
||||
try {
|
||||
temp = readTemperature();
|
||||
} catch (Exception ex) {
|
||||
System.err.println(ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
press = readPressure();
|
||||
} catch (Exception ex) {
|
||||
System.err.println(ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
hum = readHumidity();
|
||||
} catch (Exception ex) {
|
||||
System.err.println(ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the temperature in degrees celsius
|
||||
*/
|
||||
public float temperature() {
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pressure in Pa
|
||||
*/
|
||||
public float pressure() {
|
||||
return press;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the altitude in meters
|
||||
* @param pressure as returned by pressure()
|
||||
*/
|
||||
public float altitude(float pressure) {
|
||||
double altitude = 0.0;
|
||||
if (standardSeaLevelPressure != 0) {
|
||||
altitude = 44330.0 * (1.0 - Math.pow(pressure / standardSeaLevelPressure, 0.1903));
|
||||
}
|
||||
return (float)altitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the altitude in meters
|
||||
* @param pressure as returned by pressure() in Pa
|
||||
* @param temperature as returned by temperature() in Celcius
|
||||
*/
|
||||
public float altitude(float pressure, float temperature) {
|
||||
double altitude = 0.0;
|
||||
if (standardSeaLevelPressure != 0) {
|
||||
altitude = ((Math.pow(standardSeaLevelPressure / pressure, 1 / 5.257) - 1) * (temperature + 273.25)) / 0.0065;
|
||||
}
|
||||
return (float)altitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the humidity in percent
|
||||
*/
|
||||
public float humidity() {
|
||||
return hum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the standard sea level pressure used for calculating altitude()
|
||||
* Defaults to 101325 Pa (1013.25 hPa)
|
||||
*/
|
||||
public void setStandardSeaLevelPressure(float pressure) {
|
||||
standardSeaLevelPressure = pressure;
|
||||
}
|
||||
|
||||
|
||||
protected float readTemperature() {
|
||||
// Returns the compensated temperature in degrees celcius
|
||||
float UT = readRawTemp();
|
||||
float var1 = 0.0f;
|
||||
float var2 = 0.0f;
|
||||
float temp = 0.0f;
|
||||
|
||||
// Read raw temp before aligning it with the calibration values
|
||||
var1 = (UT / 16384.0f - dig_T1 / 1024.0f) * (float) dig_T2;
|
||||
var2 = ((UT / 131072.0f - dig_T1 / 8192.0f) * (UT / 131072.0f - dig_T1 / 8192.0f)) * (float) dig_T3;
|
||||
tFine = (int) (var1 + var2);
|
||||
temp = (var1 + var2) / 5120.0f;
|
||||
// println("DBG: Calibrated temperature = " + temp + " C");
|
||||
return temp;
|
||||
}
|
||||
|
||||
protected float readPressure() {
|
||||
// Returns the compensated pressure in Pascal
|
||||
int adc = readRawPressure();
|
||||
// println("ADC:" + adc + ", tFine:" + tFine);
|
||||
float var1 = (tFine / 2.0f) - 64000.0f;
|
||||
float var2 = var1 * var1 * (dig_P6 / 32768.0f);
|
||||
var2 = var2 + var1 * dig_P5 * 2.0f;
|
||||
var2 = (var2 / 4.0f) + (dig_P4 * 65536.0f);
|
||||
var1 = (dig_P3 * var1 * var1 / 524288.0f + dig_P2 * var1) / 524288.0f;
|
||||
var1 = (1.0f + var1 / 32768.0f) * dig_P1;
|
||||
if (var1 == 0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
float p = 1048576.0f - adc;
|
||||
p = ((p - var2 / 4096.0f) * 6250.0f) / var1;
|
||||
var1 = dig_P9 * p * p / 2147483648.0f;
|
||||
var2 = p * dig_P8 / 32768.0f;
|
||||
p = p + (var1 + var2 + dig_P7) / 16.0f;
|
||||
// println("DBG: Pressure = " + p + " Pa");
|
||||
return p;
|
||||
}
|
||||
|
||||
protected float readHumidity() {
|
||||
// Returns the compensated humidity in percent
|
||||
int adc = readRawHumidity();
|
||||
float h = tFine - 76800.0f;
|
||||
h = (adc - (dig_H4 * 64.0f + dig_H5 / 16384.8f * h)) *
|
||||
(dig_H2 / 65536.0f * (1.0f + dig_H6 / 67108864.0f * h * (1.0f + dig_H3 / 67108864.0f * h)));
|
||||
h = h * (1.0f - dig_H1 * h / 524288.0f);
|
||||
if (h > 100) {
|
||||
h = 100;
|
||||
} else if (h < 0) {
|
||||
h = 0;
|
||||
}
|
||||
// println("DBG: Humidity = " + h);
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
private void readCalibrationData() {
|
||||
// Reads the calibration data from the IC
|
||||
dig_T1 = readU16LE(BME280_REGISTER_DIG_T1);
|
||||
dig_T2 = readS16LE(BME280_REGISTER_DIG_T2);
|
||||
dig_T3 = readS16LE(BME280_REGISTER_DIG_T3);
|
||||
|
||||
dig_P1 = readU16LE(BME280_REGISTER_DIG_P1);
|
||||
dig_P2 = readS16LE(BME280_REGISTER_DIG_P2);
|
||||
dig_P3 = readS16LE(BME280_REGISTER_DIG_P3);
|
||||
dig_P4 = readS16LE(BME280_REGISTER_DIG_P4);
|
||||
dig_P5 = readS16LE(BME280_REGISTER_DIG_P5);
|
||||
dig_P6 = readS16LE(BME280_REGISTER_DIG_P6);
|
||||
dig_P7 = readS16LE(BME280_REGISTER_DIG_P7);
|
||||
dig_P8 = readS16LE(BME280_REGISTER_DIG_P8);
|
||||
dig_P9 = readS16LE(BME280_REGISTER_DIG_P9);
|
||||
|
||||
dig_H1 = readU8(BME280_REGISTER_DIG_H1);
|
||||
dig_H2 = readS16LE(BME280_REGISTER_DIG_H2);
|
||||
dig_H3 = readU8(BME280_REGISTER_DIG_H3);
|
||||
dig_H6 = readS8(BME280_REGISTER_DIG_H7);
|
||||
|
||||
int h4 = readS8(BME280_REGISTER_DIG_H4);
|
||||
h4 = (h4 << 24) >> 20;
|
||||
dig_H4 = h4 | (readU8(BME280_REGISTER_DIG_H5) & 0x0F);
|
||||
|
||||
int h5 = readS8(BME280_REGISTER_DIG_H6);
|
||||
h5 = (h5 << 24) >> 20;
|
||||
dig_H5 = h5 | (readU8(BME280_REGISTER_DIG_H5) >> 4 & 0x0F);
|
||||
}
|
||||
|
||||
private String displayRegister(int reg) {
|
||||
return String.format("0x%s (%d)", lpad(Integer.toHexString(reg & 0xFFFF).toUpperCase(), 4, "0"), reg);
|
||||
}
|
||||
|
||||
private void showCalibrationData() {
|
||||
// Displays the calibration values for debugging purposes
|
||||
println("======================");
|
||||
println("DBG: T1 = " + displayRegister(dig_T1));
|
||||
println("DBG: T2 = " + displayRegister(dig_T2));
|
||||
println("DBG: T3 = " + displayRegister(dig_T3));
|
||||
println("----------------------");
|
||||
println("DBG: P1 = " + displayRegister(dig_P1));
|
||||
println("DBG: P2 = " + displayRegister(dig_P2));
|
||||
println("DBG: P3 = " + displayRegister(dig_P3));
|
||||
println("DBG: P4 = " + displayRegister(dig_P4));
|
||||
println("DBG: P5 = " + displayRegister(dig_P5));
|
||||
println("DBG: P6 = " + displayRegister(dig_P6));
|
||||
println("DBG: P7 = " + displayRegister(dig_P7));
|
||||
println("DBG: P8 = " + displayRegister(dig_P8));
|
||||
println("DBG: P9 = " + displayRegister(dig_P9));
|
||||
println("----------------------");
|
||||
println("DBG: H1 = " + displayRegister(dig_H1));
|
||||
println("DBG: H2 = " + displayRegister(dig_H2));
|
||||
println("DBG: H3 = " + displayRegister(dig_H3));
|
||||
println("DBG: H4 = " + displayRegister(dig_H4));
|
||||
println("DBG: H5 = " + displayRegister(dig_H5));
|
||||
println("DBG: H6 = " + displayRegister(dig_H6));
|
||||
println("======================");
|
||||
}
|
||||
|
||||
private void command(int reg, byte val) {
|
||||
super.beginTransmission(address);
|
||||
super.write(reg);
|
||||
super.write(val);
|
||||
super.endTransmission();
|
||||
}
|
||||
|
||||
private int readRawTemp() {
|
||||
// Returns the raw (uncompensated) temperature
|
||||
int meas = mode;
|
||||
// println(String.format("readRawTemp: 1 - meas=%d", meas));
|
||||
command(BME280_REGISTER_CONTROL_HUM, (byte) meas); // HUM ?
|
||||
meas = mode << 5 | mode << 2 | 1;
|
||||
// println(String.format("readRawTemp: 2 - meas=%d", meas));
|
||||
command(BME280_REGISTER_CONTROL, (byte) meas);
|
||||
|
||||
double sleepTime = 0.00125 + 0.0023 * (1 << mode);
|
||||
sleepTime = sleepTime + 0.0023 * (1 << mode) + 0.000575;
|
||||
sleepTime = sleepTime + 0.0023 * (1 << mode) + 0.000575;
|
||||
delay((int)Math.round(sleepTime * 1000));
|
||||
int msb = readU8(BME280_REGISTER_TEMP_DATA);
|
||||
int lsb = readU8(BME280_REGISTER_TEMP_DATA + 1);
|
||||
int xlsb = readU8(BME280_REGISTER_TEMP_DATA + 2);
|
||||
int raw = ((msb << 16) | (lsb << 8) | xlsb) >> 4;
|
||||
// println("DBG: Raw Temp: " + (raw & 0xFFFF) + ", " + raw + String.format(", msb: 0x%04X lsb: 0x%04X xlsb: 0x%04X", msb, lsb, xlsb));
|
||||
return raw;
|
||||
}
|
||||
|
||||
private int readRawPressure() {
|
||||
// Returns the raw (uncompensated) pressure
|
||||
int msb = readU8(BME280_REGISTER_PRESSURE_DATA);
|
||||
int lsb = readU8(BME280_REGISTER_PRESSURE_DATA + 1);
|
||||
int xlsb = readU8(BME280_REGISTER_PRESSURE_DATA + 2);
|
||||
int raw = ((msb << 16) | (lsb << 8) | xlsb) >> 4;
|
||||
// println("DBG: Raw Press: " + (raw & 0xFFFF) + ", " + raw + String.format(", msb: 0x%04X lsb: 0x%04X xlsb: 0x%04X", msb, lsb, xlsb));
|
||||
return raw;
|
||||
}
|
||||
|
||||
private int readRawHumidity() {
|
||||
// Returns the raw (uncompensated) humidity
|
||||
int msb = readU8(BME280_REGISTER_HUMIDITY_DATA);
|
||||
int lsb = readU8(BME280_REGISTER_HUMIDITY_DATA + 1);
|
||||
int raw = (msb << 8) | lsb;
|
||||
return raw;
|
||||
}
|
||||
|
||||
private int readU16LE(int register) {
|
||||
super.beginTransmission(address);
|
||||
super.write((byte)register);
|
||||
byte[] ba = super.read(2);
|
||||
super.endTransmission();
|
||||
return ((ba[1] & 0xFF) << 8) + (ba[0] & 0xFF); // Little Endian
|
||||
}
|
||||
|
||||
private int readS16LE(int register) {
|
||||
super.beginTransmission(address);
|
||||
super.write((byte)register);
|
||||
byte[] ba = super.read(2);
|
||||
super.endTransmission();
|
||||
|
||||
int lo = ba[0] & 0xFF;
|
||||
int hi = ba[1] & 0xFF;
|
||||
if (hi > 127)
|
||||
hi -= 256;
|
||||
return (hi << 8) + lo; // Little Endian
|
||||
}
|
||||
|
||||
private int readU8(int register) {
|
||||
super.beginTransmission(address);
|
||||
super.write(register);
|
||||
byte[] ba = super.read(1);
|
||||
super.endTransmission();
|
||||
return (int)(ba[0] & 0xFF);
|
||||
}
|
||||
|
||||
private int readS8(int register) {
|
||||
int val = readU8(register);
|
||||
if (val > 127)
|
||||
val -= 256;
|
||||
return val;
|
||||
}
|
||||
|
||||
private String rpad(String s, int len, String pad) {
|
||||
String str = s;
|
||||
while (str.length() < len) {
|
||||
str += pad;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
private String lpad(String s, int len, String pad) {
|
||||
String str = s;
|
||||
while (str.length() < len) {
|
||||
str = pad + str;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import processing.io.*;
|
||||
BME280 bme280;
|
||||
|
||||
// see setup.png in the sketch folder for wiring details
|
||||
|
||||
void setup() {
|
||||
size(720, 320);
|
||||
textSize(72);
|
||||
|
||||
//printArray(I2C.list());
|
||||
bme280 = new BME280("i2c-1", 0x77);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
stroke(255);
|
||||
|
||||
bme280.update();
|
||||
float temp = bme280.temperature();
|
||||
float hum = bme280.humidity();
|
||||
float press = bme280.pressure();
|
||||
text(String.format("Temp: %.02f\272C", temp), 10, 75);
|
||||
text(String.format("Hum: %.02f %%", hum), 10, 150);
|
||||
text(String.format("Press: %.02f hPa", press / 100f), 10, 225);
|
||||
|
||||
// pressure can be used to calculate the altitude like so
|
||||
float alt = bme280.altitude(press, temp);
|
||||
text(String.format("Alt: %.02f m", alt), 10, 300);
|
||||
}
|
||||
|
After Width: | Height: | Size: 227 KiB |
@@ -0,0 +1,25 @@
|
||||
import processing.io.*;
|
||||
color bgcolor = 0;
|
||||
|
||||
// GPIO numbers refer to different phyiscal pins on various boards
|
||||
// On the Raspberry Pi GPIO 4 is physical pin 7 on the header
|
||||
// see setup.png in the sketch folder for wiring details
|
||||
|
||||
void setup() {
|
||||
GPIO.pinMode(4, GPIO.INPUT);
|
||||
GPIO.attachInterrupt(4, this, "pinEvent", GPIO.RISING);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(bgcolor);
|
||||
}
|
||||
|
||||
// this function will be called whenever GPIO 4 is brought from LOW to HIGH
|
||||
void pinEvent(int pin) {
|
||||
println("Received interrupt");
|
||||
if (bgcolor == 0) {
|
||||
bgcolor = color(255);
|
||||
} else {
|
||||
bgcolor = color(0);
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 193 KiB |
@@ -0,0 +1,39 @@
|
||||
import processing.io.*;
|
||||
LED leds[];
|
||||
|
||||
// the Raspberry Pi has two build-in LEDs we can control
|
||||
// led0 (green) and led1 (red)
|
||||
|
||||
void setup() {
|
||||
String available[] = LED.list();
|
||||
print("Available: ");
|
||||
println(available);
|
||||
|
||||
// create an object for each LED and store it in an array
|
||||
leds = new LED[available.length];
|
||||
for (int i=0; i < available.length; i++) {
|
||||
leds[i] = new LED(available[i]);
|
||||
}
|
||||
|
||||
frameRate(1);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
// make the LEDs count in binary
|
||||
for (int i=0; i < leds.length; i++) {
|
||||
if ((frameCount & (1 << i)) != 0) {
|
||||
leds[i].brightness(1.0);
|
||||
} else {
|
||||
leds[i].brightness(0.0);
|
||||
}
|
||||
}
|
||||
println(frameCount);
|
||||
}
|
||||
|
||||
void keyPressed() {
|
||||
// cleanup
|
||||
for (int i=0; i < leds.length; i++) {
|
||||
leds[i].close();
|
||||
}
|
||||
exit();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import processing.io.*;
|
||||
TSL2561 sensor;
|
||||
|
||||
// see setup.png in the sketch folder for wiring details
|
||||
|
||||
// this variable will contain the measured brightness
|
||||
// Lux (lx) is the unit of illuminance
|
||||
float lux;
|
||||
|
||||
void setup() {
|
||||
size(700, 100);
|
||||
textSize(72);
|
||||
//printArray(I2C.list());
|
||||
sensor = new TSL2561("i2c-1", 0x39);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
stroke(255);
|
||||
lux = sensor.lux();
|
||||
text(String.format("Light: %.02f Lux", lux), 10, 75);
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
// turn the sensor off
|
||||
sensor.stop();
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
import processing.io.I2C;
|
||||
|
||||
// TSL2561 is light sensor using I2C
|
||||
// datasheet: https://cdn-shop.adafruit.com/datasheets/TSL2561.pdf
|
||||
// code contributed by @OlivierLD
|
||||
|
||||
public class TSL2561 extends I2C {
|
||||
|
||||
public final static int TSL2561_ADDRESS = 0x39;
|
||||
|
||||
public final static int TSL2561_ADDRESS_LOW = 0x29;
|
||||
public final static int TSL2561_ADDRESS_FLOAT = 0x39;
|
||||
public final static int TSL2561_ADDRESS_HIGH = 0x49;
|
||||
|
||||
public final static int TSL2561_COMMAND_BIT = 0x80;
|
||||
public final static int TSL2561_WORD_BIT = 0x20;
|
||||
public final static int TSL2561_CONTROL_POWERON = 0x03;
|
||||
public final static int TSL2561_CONTROL_POWEROFF = 0x00;
|
||||
|
||||
public final static int TSL2561_REGISTER_CONTROL = 0x00;
|
||||
public final static int TSL2561_REGISTER_TIMING = 0x01;
|
||||
public final static int TSL2561_REGISTER_CHAN0_LOW = 0x0C;
|
||||
public final static int TSL2561_REGISTER_CHAN0_HIGH = 0x0D;
|
||||
public final static int TSL2561_REGISTER_CHAN1_LOW = 0x0E;
|
||||
public final static int TSL2561_REGISTER_CHAN1_HIGH = 0x0F;
|
||||
public final static int TSL2561_REGISTER_ID = 0x0A;
|
||||
|
||||
public final static int TSL2561_GAIN_1X = 0x00;
|
||||
public final static int TSL2561_GAIN_16X = 0x10;
|
||||
|
||||
public final static int TSL2561_INTEGRATIONTIME_13MS = 0x00; // rather 13.7ms
|
||||
public final static int TSL2561_INTEGRATIONTIME_101MS = 0x01;
|
||||
public final static int TSL2561_INTEGRATIONTIME_402MS = 0x02;
|
||||
|
||||
public final static double TSL2561_LUX_K1C = 0.130; // (0x0043) // 0.130 * 2^RATIO_SCALE
|
||||
public final static double TSL2561_LUX_B1C = 0.0315; // (0x0204) // 0.0315 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_M1C = 0.0262; // (0x01ad) // 0.0262 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_K2C = 0.260; // (0x0085) // 0.260 * 2^RATIO_SCALE
|
||||
public final static double TSL2561_LUX_B2C = 0.0337; // (0x0228) // 0.0337 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_M2C = 0.0430; // (0x02c1) // 0.0430 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_K3C = 0.390; // (0x00c8) // 0.390 * 2^RATIO_SCALE
|
||||
public final static double TSL2561_LUX_B3C = 0.0363; // (0x0253) // 0.0363 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_M3C = 0.0529; // (0x0363) // 0.0529 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_K4C = 0.520; // (0x010a) // 0.520 * 2^RATIO_SCALE
|
||||
public final static double TSL2561_LUX_B4C = 0.0392; // (0x0282) // 0.0392 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_M4C = 0.0605; // (0x03df) // 0.0605 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_K5C = 0.65; // (0x014d) // 0.65 * 2^RATIO_SCALE
|
||||
public final static double TSL2561_LUX_B5C = 0.0229; // (0x0177) // 0.0229 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_M5C = 0.0291; // (0x01dd) // 0.0291 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_K6C = 0.80; // (0x019a) // 0.80 * 2^RATIO_SCALE
|
||||
public final static double TSL2561_LUX_B6C = 0.0157; // (0x0101) // 0.0157 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_M6C = 0.0180; // (0x0127) // 0.0180 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_K7C = 1.3; // (0x029a) // 1.3 * 2^RATIO_SCALE
|
||||
public final static double TSL2561_LUX_B7C = 0.00338; // (0x0037) // 0.00338 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_M7C = 0.00260; // (0x002b) // 0.00260 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_K8C = 1.3; // (0x029a) // 1.3 * 2^RATIO_SCALE
|
||||
public final static double TSL2561_LUX_B8C = 0.000; // (0x0000) // 0.000 * 2^LUX_SCALE
|
||||
public final static double TSL2561_LUX_M8C = 0.000; // (0x0000) // 0.000 * 2^LUX_SCALE
|
||||
|
||||
private int gain = TSL2561_GAIN_1X;
|
||||
private int integration = TSL2561_INTEGRATIONTIME_402MS;
|
||||
private int pause = 800;
|
||||
|
||||
private int address;
|
||||
|
||||
|
||||
public TSL2561(String dev) {
|
||||
this(dev, TSL2561_ADDRESS);
|
||||
}
|
||||
|
||||
public TSL2561(String dev, int address) {
|
||||
super(dev);
|
||||
this.address = address;
|
||||
start();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
command(TSL2561_COMMAND_BIT, (byte) TSL2561_CONTROL_POWERON);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
command(TSL2561_COMMAND_BIT, (byte) TSL2561_CONTROL_POWEROFF);
|
||||
}
|
||||
|
||||
public void setGain() {
|
||||
setGain(TSL2561_GAIN_1X);
|
||||
}
|
||||
|
||||
public void setGain(int gain) {
|
||||
setGain(gain, TSL2561_INTEGRATIONTIME_402MS);
|
||||
}
|
||||
|
||||
public void setGain(int gain, int integration) {
|
||||
if (gain != TSL2561_GAIN_1X && gain != TSL2561_GAIN_16X) {
|
||||
throw new IllegalArgumentException("Invalid gain value");
|
||||
}
|
||||
if (gain != this.gain || integration != this.integration) {
|
||||
command(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, (byte) (gain | integration));
|
||||
//println("Setting low gain");
|
||||
this.gain = gain;
|
||||
this.integration = integration;
|
||||
delay(pause); // pause for integration (pause must be bigger than integration time)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read visible+IR diode from the I2C device
|
||||
*/
|
||||
public int readFull() {
|
||||
int reg = TSL2561_COMMAND_BIT | TSL2561_REGISTER_CHAN0_LOW;
|
||||
return readU16(reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read IR only diode from the I2C device
|
||||
*/
|
||||
public int readIR() {
|
||||
int reg = TSL2561_COMMAND_BIT | TSL2561_REGISTER_CHAN1_LOW;
|
||||
return readU16(reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Device lux range 0.1 - 40,000+
|
||||
* see https://learn.adafruit.com/tsl2561/overview
|
||||
*/
|
||||
public float lux() {
|
||||
int ambient = this.readFull();
|
||||
int ir = this.readIR();
|
||||
|
||||
//println("IR Result: " + ir);
|
||||
//println("Ambient Result: " + ambient);
|
||||
|
||||
if (ambient >= 0xffff || ir >= 0xffff) {
|
||||
throw new RuntimeException("Gain too high, values exceed range");
|
||||
}
|
||||
double ratio = (ir / (float) ambient);
|
||||
|
||||
/*
|
||||
* For the values below, see https://github.com/adafruit/_TSL2561/blob/master/_TSL2561_U.h
|
||||
*/
|
||||
float lux = 0.0f;
|
||||
if ((ratio >= 0) && (ratio <= TSL2561_LUX_K4C)) {
|
||||
lux = (float)((TSL2561_LUX_B1C * ambient) - (0.0593 * ambient * (Math.pow(ratio, 1.4))));
|
||||
} else if (ratio <= TSL2561_LUX_K5C) {
|
||||
lux = (float)((TSL2561_LUX_B5C * ambient) - (TSL2561_LUX_M5C * ir));
|
||||
} else if (ratio <= TSL2561_LUX_K6C) {
|
||||
lux = (float)((TSL2561_LUX_B6C * ambient) - (TSL2561_LUX_M6C * ir));
|
||||
} else if (ratio <= TSL2561_LUX_K7C) {
|
||||
lux = (float)((TSL2561_LUX_B7C * ambient) - (TSL2561_LUX_M7C * ir));
|
||||
} else if (ratio > TSL2561_LUX_K8C) {
|
||||
lux = 0.0f;
|
||||
}
|
||||
return lux;
|
||||
}
|
||||
|
||||
|
||||
private void command(int register, byte value) {
|
||||
beginTransmission(address);
|
||||
write(register);
|
||||
write(value);
|
||||
endTransmission();
|
||||
}
|
||||
|
||||
private int readU8(int register) {
|
||||
beginTransmission(this.address);
|
||||
write(register);
|
||||
byte[] ba = read(1);
|
||||
endTransmission();
|
||||
return (int)(ba[0] & 0xFF);
|
||||
}
|
||||
|
||||
private int readU16(int register) {
|
||||
int lo = readU8(register);
|
||||
int hi = readU8(register + 1);
|
||||
int result = (hi << 8) + lo; // Big Endian
|
||||
//println("(U16) I2C: Device " + toHex(TSL2561_ADDRESS) + " returned " + toHex(result) + " from reg " + toHex(register));
|
||||
return result;
|
||||
}
|
||||
|
||||
private String toHex(int i) {
|
||||
String s = Integer.toString(i, 16).toUpperCase();
|
||||
while (s.length() % 2 != 0) {
|
||||
s = "0" + s;
|
||||
}
|
||||
return "0x" + s;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 224 KiB |
@@ -0,0 +1,148 @@
|
||||
import processing.io.I2C;
|
||||
|
||||
// PCA9685 is a 16-channel servo/PWM driver
|
||||
// datasheet: https://cdn-shop.adafruit.com/datasheets/PCA9685.pdf
|
||||
// code contributed by @OlivierLD
|
||||
|
||||
public class PCA9685 extends I2C {
|
||||
public final static int PCA9685_ADDRESS = 0x40;
|
||||
|
||||
// registers used
|
||||
public final static int MODE1 = 0x00;
|
||||
public final static int PRESCALE = 0xFE;
|
||||
public final static int LED0_ON_L = 0x06;
|
||||
public final static int LED0_ON_H = 0x07;
|
||||
public final static int LED0_OFF_L = 0x08;
|
||||
public final static int LED0_OFF_H = 0x09;
|
||||
|
||||
private int address;
|
||||
private int freq = 200; // 200 Hz default frequency (after power-up)
|
||||
private boolean hasFreqSet = false; // whether a different frequency has been set
|
||||
private int minPulses[] = new int[16];
|
||||
private int maxPulses[] = new int[16];
|
||||
|
||||
|
||||
public PCA9685(String dev) {
|
||||
this(dev, PCA9685_ADDRESS);
|
||||
}
|
||||
public PCA9685(String dev, int address) {
|
||||
super(dev);
|
||||
this.address = address;
|
||||
// reset device
|
||||
command(MODE1, (byte) 0x00);
|
||||
}
|
||||
|
||||
|
||||
public void attach(int channel) {
|
||||
// same as on Arduino
|
||||
attach(channel, 544, 2400);
|
||||
}
|
||||
|
||||
public void attach(int channel, int minPulse, int maxPulse) {
|
||||
if (channel < 0 || 15 < channel) {
|
||||
throw new IllegalArgumentException("Channel must be between 0 and 15");
|
||||
}
|
||||
minPulses[channel] = minPulse;
|
||||
maxPulses[channel] = maxPulse;
|
||||
|
||||
// set the PWM frequency to be the same as on Arduino
|
||||
if (!hasFreqSet) {
|
||||
frequency(50);
|
||||
}
|
||||
}
|
||||
|
||||
public void write(int channel, float angle) {
|
||||
if (channel < 0 || 15 < channel) {
|
||||
throw new IllegalArgumentException("Channel must be between 0 and 15");
|
||||
}
|
||||
if (angle < 0 || 180 < angle) {
|
||||
throw new IllegalArgumentException("Angle must be between 0 and 180");
|
||||
}
|
||||
int us = (int)(minPulses[channel] + (angle/180.0) * (maxPulses[channel]-minPulses[channel]));
|
||||
|
||||
double pulseLength = 1000000; // 1s = 1,000,000 us per pulse
|
||||
pulseLength /= freq; // 40..1000 Hz
|
||||
pulseLength /= 4096; // 12 bits of resolution
|
||||
int pulse = us;
|
||||
pulse /= pulseLength;
|
||||
// println(pulseLength + " us per bit, pulse:" + pulse);
|
||||
pwm(channel, 0, pulse);
|
||||
}
|
||||
|
||||
public boolean attached(int channel) {
|
||||
if (channel < 0 || 15 < channel) {
|
||||
return false;
|
||||
}
|
||||
return (maxPulses[channel] != 0) ? true : false;
|
||||
}
|
||||
|
||||
public void detach(int channel) {
|
||||
pwm(channel, 0, 0);
|
||||
minPulses[channel] = 0;
|
||||
maxPulses[channel] = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param freq 40..1000 Hz
|
||||
*/
|
||||
public void frequency(int freq) {
|
||||
this.freq = freq;
|
||||
float preScaleVal = 25000000.0f; // 25MHz
|
||||
preScaleVal /= 4096.0; // 4096: 12-bit
|
||||
preScaleVal /= freq;
|
||||
preScaleVal -= 1.0;
|
||||
// println("Setting PWM frequency to " + freq + " Hz");
|
||||
// println("Estimated pre-scale: " + preScaleVal);
|
||||
double preScale = Math.floor(preScaleVal + 0.5);
|
||||
// println("Final pre-scale: " + preScale);
|
||||
byte oldmode = (byte) readU8(MODE1);
|
||||
byte newmode = (byte) ((oldmode & 0x7F) | 0x10); // sleep
|
||||
command(MODE1, newmode); // go to sleep
|
||||
command(PRESCALE, (byte) (Math.floor(preScale)));
|
||||
command(MODE1, oldmode);
|
||||
delay(5);
|
||||
command(MODE1, (byte) (oldmode | 0x80));
|
||||
hasFreqSet = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channel 0..15
|
||||
* @param on cycle offset to turn output on (0..4095)
|
||||
* @param off cycle offset to turn output off again (0..4095)
|
||||
*/
|
||||
public void pwm(int channel, int on, int off) {
|
||||
if (channel < 0 || 15 < channel) {
|
||||
throw new IllegalArgumentException("Channel must be between 0 and 15");
|
||||
}
|
||||
if (on < 0 || 4095 < on) {
|
||||
throw new IllegalArgumentException("On must be between 0 and 4095");
|
||||
}
|
||||
if (off < 0 || 4095 < off) {
|
||||
throw new IllegalArgumentException("Off must be between 0 and 4095");
|
||||
}
|
||||
if (off < on) {
|
||||
throw new IllegalArgumentException("Off must be greater than On");
|
||||
}
|
||||
command(LED0_ON_L + 4 * channel, (byte) (on & 0xFF));
|
||||
command(LED0_ON_H + 4 * channel, (byte) (on >> 8));
|
||||
command(LED0_OFF_L + 4 * channel, (byte) (off & 0xFF));
|
||||
command(LED0_OFF_H + 4 * channel, (byte) (off >> 8));
|
||||
}
|
||||
|
||||
|
||||
private void command(int register, byte value) {
|
||||
beginTransmission(address);
|
||||
write(register);
|
||||
write(value);
|
||||
endTransmission();
|
||||
}
|
||||
|
||||
private byte readU8(int register) {
|
||||
beginTransmission(address);
|
||||
write(register);
|
||||
byte[] ba = read(1);
|
||||
endTransmission();
|
||||
return (byte)(ba[0] & 0xFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import processing.io.*;
|
||||
PCA9685 servos;
|
||||
|
||||
// see setup.png in the sketch folder for wiring details
|
||||
|
||||
void setup() {
|
||||
size(400, 300);
|
||||
//printArray(I2C.list());
|
||||
servos = new PCA9685("i2c-1", 0x40);
|
||||
|
||||
// different servo motors will vary in the pulse width they expect
|
||||
// the lines below set the pulse width for 0 degrees to 544 microseconds (μs)
|
||||
// and the pulse width for 180 degrees to 2400 microseconds
|
||||
// these values match the defaults of the Servo library on Arduino
|
||||
// but you might need to modify this for your particular servo still
|
||||
servos.attach(0, 544, 2400);
|
||||
servos.attach(1, 544, 2400);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
stroke(255);
|
||||
strokeWeight(3);
|
||||
|
||||
// we don't go right to the edge to prevent
|
||||
// making the servo unhappy
|
||||
float angle = 90 + sin(frameCount / 100.0)*85;
|
||||
servos.write(0, angle);
|
||||
float y = map(angle, 0, 180, 0, height);
|
||||
line(0, y, width/2, y);
|
||||
|
||||
angle = 90 + cos(frameCount / 100.0)*85;
|
||||
servos.write(1, 90 + cos(frameCount / 100.0)*85);
|
||||
y = map(angle, 0, 180, 0, height);
|
||||
line(width/2, y, width, y);
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
servos.detach(0);
|
||||
servos.detach(1);
|
||||
}
|
||||
|
After Width: | Height: | Size: 253 KiB |
@@ -0,0 +1,30 @@
|
||||
import processing.io.*;
|
||||
I2C i2c;
|
||||
|
||||
// MCP4725 is a Digital-to-Analog converter using I2C
|
||||
// datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22039d.pdf
|
||||
|
||||
// also see DigitalAnalog_I2C_MCP4725 for how to write the
|
||||
// same sketch in an object-oriented way
|
||||
|
||||
void setup() {
|
||||
//printArray(I2C.list());
|
||||
i2c = new I2C(I2C.list()[0]);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(map(mouseX, 0, width, 0, 255));
|
||||
setAnalog(map(mouseX, 0, width, 0.0, 1.0));
|
||||
}
|
||||
|
||||
// outputs voltages from 0V to the supply voltage
|
||||
// (works with 3.3V and 5V)
|
||||
void setAnalog(float fac) {
|
||||
fac = constrain(fac, 0.0, 1.0);
|
||||
// convert to 12 bit value
|
||||
int val = int(4095 * fac);
|
||||
i2c.beginTransmission(0x60);
|
||||
i2c.write(val >> 8);
|
||||
i2c.write(val & 255);
|
||||
i2c.endTransmission();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import processing.io.*;
|
||||
|
||||
// GPIO numbers refer to different phyiscal pins on various boards
|
||||
// On the Raspberry Pi GPIO 4 is physical pin 7 on the header
|
||||
// see setup.png in the sketch folder for wiring details
|
||||
|
||||
void setup() {
|
||||
// INPUT_PULLUP enables the built-in pull-up resistor for this pin
|
||||
// left alone, the pin will read as HIGH
|
||||
// connected to ground (via e.g. a button or switch) it will read LOW
|
||||
GPIO.pinMode(4, GPIO.INPUT_PULLUP);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
if (GPIO.digitalRead(4) == GPIO.LOW) {
|
||||
// button is pressed
|
||||
fill(255);
|
||||
} else {
|
||||
// button is not pressed
|
||||
fill(204);
|
||||
}
|
||||
stroke(255);
|
||||
ellipse(width/2, height/2, width*0.75, height*0.75);
|
||||
}
|
||||
|
After Width: | Height: | Size: 193 KiB |
@@ -0,0 +1,25 @@
|
||||
import processing.io.*;
|
||||
boolean ledOn = false;
|
||||
|
||||
// GPIO numbers refer to different phyiscal pins on various boards
|
||||
// On the Raspberry Pi GPIO 4 is physical pin 7 on the header
|
||||
// see setup.png in the sketch folder for wiring details
|
||||
|
||||
void setup() {
|
||||
GPIO.pinMode(4, GPIO.OUTPUT);
|
||||
frameRate(0.5);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
// make the LED blink
|
||||
ledOn = !ledOn;
|
||||
if (ledOn) {
|
||||
GPIO.digitalWrite(4, GPIO.LOW);
|
||||
fill(204);
|
||||
} else {
|
||||
GPIO.digitalWrite(4, GPIO.HIGH);
|
||||
fill(255);
|
||||
}
|
||||
stroke(255);
|
||||
ellipse(width/2, height/2, width*0.75, height*0.75);
|
||||
}
|
||||
|
After Width: | Height: | Size: 194 KiB |
@@ -0,0 +1,56 @@
|
||||
import processing.io.*;
|
||||
|
||||
// using a capacitor that gets charged and discharged, while
|
||||
// measuring the time it takes, is an inexpensive way to
|
||||
// read the value of an (analog) resistive sensor, such as
|
||||
// a photocell
|
||||
// kudos to ladyada for the original tutorial
|
||||
|
||||
// see setup.png in the sketch folder for wiring details
|
||||
|
||||
int max = 0;
|
||||
int min = 9999;
|
||||
|
||||
void setup() {
|
||||
}
|
||||
|
||||
void draw() {
|
||||
int val = sensorRead(4);
|
||||
println(val);
|
||||
|
||||
// track largest and smallest reading, to get a sense
|
||||
// how we compare
|
||||
if (max < val) {
|
||||
max = val;
|
||||
}
|
||||
if (val < min) {
|
||||
min = val;
|
||||
}
|
||||
|
||||
// convert current reading into a number between 0.0 and 1.0
|
||||
float frac = map(val, min, max, 0.0, 1.0);
|
||||
|
||||
background(255 * frac);
|
||||
}
|
||||
|
||||
int sensorRead(int pin) {
|
||||
// discharge the capacitor
|
||||
GPIO.pinMode(pin, GPIO.OUTPUT);
|
||||
GPIO.digitalWrite(pin, GPIO.LOW);
|
||||
delay(100);
|
||||
// now the capacitor should be empty
|
||||
|
||||
// measure the time takes to fill it
|
||||
// up to ~ 1.4V again
|
||||
GPIO.pinMode(pin, GPIO.INPUT);
|
||||
int start = millis();
|
||||
while (GPIO.digitalRead(pin) == GPIO.LOW) {
|
||||
// wait
|
||||
}
|
||||
|
||||
// return the time elapsed
|
||||
// this will vary based on the value of the
|
||||
// resistive sensor (lower resistance will
|
||||
// make the capacitor charge faster)
|
||||
return millis() - start;
|
||||
}
|
||||