Code: Select all
#!/usr/bin/env python
# i2c_ADXL345.py este es el accelerómetro de 3 ejes
# 2015-04-01
# Public Domain
import time
import struct
import sys
import pigpio # http://abyz.co.uk/rpi/pigpio/python.html
if sys.version > '3':
buffer = memoryview
BUS=0
ADXL345_I2C_ADDR=0x53
#RUNTIME=60.0 This is the original line.
RUNTIME=0.10
pi=pigpio.pi() # open local Pi
h = pi.i2c_open(BUS, ADXL345_I2C_ADDR)
if h >= 0: # Connected OK?
# Initialise ADXL345.
pi.i2c_write_byte_data(h, 0x2d, 0) # POWER_CTL reset.
pi.i2c_write_byte_data(h, 0x2d, 8) # POWER_CTL measure.
pi.i2c_write_byte_data(h, 0x31, 0) # DATA_FORMAT reset.
pi.i2c_write_byte_data(h, 0x31, 11) # DATA_FORMAT full res +/- 16g.
read = 0
start_time = time.time()
while (time.time()-start_time) < RUNTIME:
# 0x32 = X LSB, 0x33 = X MSB
# 0x34 = Y LSB, 0x35 = Y MSB
# 0x36 = Z LSB, 0x37 = Z MSB
# < = little endian
(s, b) = pi.i2c_read_i2c_block_data(h, 0x32, 6)
if s >= 0:
(x, y, z) = struct.unpack('<3h', buffer(b))
print("{} {} {}".format(x, y, z))
read += 1
pi.i2c_close(h)
pi.stop()
print(read, read/RUNTIME)
How might it be possible to convert these values into angles?
Have a great afternoon!

Edit: The following is our "version" of Jay's program as of this writing... It shows the incorporation of Joan's scripts.
Code: Select all
#solarrobot7-core.py to be placed in /tools/
#!/usr/bin/python
#Version Notes
#39: Brought over from solar robot 7, cleanup of OpenElectrons code (going back to a Pololu controller)
#40: Code optimizations for Raspberry Pi A+
#42: Code cleanup, added debug toggle
from __future__ import print_function
import time, math
import serial, pysolar, datetime
from dual_mc33926_rpi import motors, MAX_SPEED
import os
assert os.path.exists('/tools/inputs/masterinputs.txt')
#digital stuff
import RPi.GPIO as GPIO
#Beginning of Joan's script for ADXL345
#!/usr/bin/env python
# i2c_ADXL345.py this is the 3 axis accelerometer
# 2015-04-01 And is Joan's script
# Public Domain
# Note - Don't forget to run pigpiod first
import time
import struct
import sys
import pigpio # http://abyz.co.uk/rpi/pigpio/python.html
if sys.version > '3':
buffer = memoryview
BUS=0
ADXL345_I2C_ADDR=0x53
pi=pigpio.pi() # open local Pi
h = pi.i2c_open(BUS, ADXL345_I2C_ADDR)
if h >= 0: # Connected OK?
# Initialise ADXL345.
pi.i2c_write_byte_data(h, 0x2d, 0) # POWER_CTL reset.
pi.i2c_write_byte_data(h, 0x2d, 8) # POWER_CTL measure.
pi.i2c_write_byte_data(h, 0x31, 0) # DATA_FORMAT reset.
pi.i2c_write_byte_data(h, 0x31, 11) # DATA_FORMAT full res +/- 16g.
read = 0
(s, b) = pi.i2c_read_i2c_block_data(h, 0x32, 6)
if s >= 0:
(accelerometerx, y, z) = struct.unpack('<3h', buffer(b))
print("{}".format(accelerometerx))
read += 1
pi.i2c_close(h)
pi.stop()
print()
#End of Joan's script for ADXL345
#Beginning of Joan's script for HMC338L
#!/usr/bin/env python
# i2c_HMC5883L.py este es la brújula (compass) de 3 ejes
# 2015-04-01
# Public Domain
import pigpio # http://abyz.co.uk/rpi/pigpio/python.html
if sys.version > '3':
buffer = memoryview
BUS=0
M_PI = 3.14159265358979323846
HMC5883L_I2C_ADDR=0x1E
pi=pigpio.pi() # open local Pi
h = pi.i2c_open(BUS, HMC5883L_I2C_ADDR)
if h >= 0: # Connected OK?
# Initialise HMC5883L.
pi.i2c_write_byte_data(h, 0x00, 0xF8) # CRA 75Hz.
pi.i2c_write_byte_data(h, 0x02, 0x00) # Mode continuous reads.
read = 0
(s, b) = pi.i2c_read_i2c_block_data(h, 0x03, 6)
if s >= 0:
(headingx, y, z) = struct.unpack('>3h', buffer(b))
headingx = 180 * math.atan2(y,headingx)/M_PI
if headingx < 0:
headingx += 360
print("{} {} {}".format(headingx, y, z))
read += 1
pi.i2c_close(h)
pi.stop()
#End of Joan's HMC5883 script.
#Beginning of Joan's ITG3205 gyroscope script
#!/usr/bin/env python
# i2c_ITG3205.py
# 2015-04-01
# Public Domain
import pigpio # http://abyz.co.uk/rpi/pigpio/python.html
if sys.version > '3':
buffer = memoryview
BUS=0
ITG_3205_I2C_ADDR=0x68
# Registers.
ITG_3205_WHO_AM_I = 0x00 # R/W
ITG_3205_SMPLRT_DIV = 0x15 # R/W
ITG_3205_DLPF_FS = 0x16 # R/W
ITG_3205_INT_CFG = 0x17 # R/W
ITG_3205_INT_STATUS = 0x1A # R
ITG_3205_TEMP_OUT_H = 0x1B # R
ITG_3205_TEMP_OUT_L = 0x1C # R
ITG_3205_GYRO_XOUT_H = 0x1D # R
ITG_3205_GYRO_XOUT_L = 0x1E # R
ITG_3205_GYRO_YOUT_H = 0x1F # R
ITG_3205_GYRO_YOUT_L = 0x20 # R
ITG_3205_GYRO_ZOUT_H = 0x21 # R
ITG_3205_GYRO_ZOUT_L = 0x22 # R
ITG_3205_PWR_MGM = 0x3E # R/W
# DLPF_FS
ITG_3205_FS_SEL_2000_DEG_SEC = 0x18
ITG_3205_DLPF_CFG_256_8 = 0x00
ITG_3205_DLPF_CFG_188_1 = 0x01
ITG_3205_DLPF_CFG_98_1 = 0x02
ITG_3205_DLPF_CFG_42_1 = 0x03
ITG_3205_DLPF_CFG_20_1 = 0x04
ITG_3205_DLPF_CFG_10_1 = 0x05
ITG_3205_DLPF_CFG_5_1 = 0x06
# INT_CFG
ITG_3205_IC_ACTL = 0x80
ITG_3205_IC_OPEN = 0x40
ITG_3205_IC_LATCH_INT_EN = 0x20
ITG_3205_IC_INT_ANYRD_2CLEAR = 0x10
ITG_3205_IC_ITG_RDY_EN = 0x04
ITG_3205_IC_RAW_RDY_EN = 0x01
# INT_STATUS
ITG_3205_IS_ITG_RDY = 0x04
ITG_3205_IS_RAW_DATA_RDY = 0x01
# PWR_MGM
ITG_3205_PM_H_RESET = 0x80
ITG_3205_PM_SLEEP = 0x40
ITG_3205_PM_STBY_XG = 0x20
ITG_3205_PM_STBY_YG = 0x10
ITG_3205_PM_STBY_ZG = 0x08
ITG_3205_PM_CLK_SEL_INTERNAL = 0x00
ITG_3205_PM_CLK_SEL_X_GYRO = 0x01
ITG_3205_PM_CLK_SEL_Y_GYRO = 0x02
ITG_3205_PM_CLK_SEL_Z_GYRO = 0x03
ITG_3205_PM_CLK_SEL_EXT_32768 = 0x04
ITG_3205_PM_CLK_SEL_EXT_192 = 0x05
pi=pigpio.pi() # open local Pi
h = pi.i2c_open(BUS, ITG_3205_I2C_ADDR)
if h >= 0: # Connected OK?
# Initialise ITG_3205.
pi.i2c_write_byte_data(h, ITG_3205_PWR_MGM, ITG_3205_PM_CLK_SEL_X_GYRO)
# 0x3E 0x01
pi.i2c_write_byte_data(h, ITG_3205_SMPLRT_DIV, 0x07)
# 0x15 0x07
pi.i2c_write_byte_data(h, ITG_3205_DLPF_FS,
ITG_3205_FS_SEL_2000_DEG_SEC | ITG_3205_DLPF_CFG_188_1)
# 0x16 0x18| 0x01
pi.i2c_write_byte_data(h, ITG_3205_INT_CFG, 0x00)
# 0x17 0x00
read = 0
(s, b) = pi.i2c_read_i2c_block_data(h, ITG_3205_TEMP_OUT_H, 8)
if s >= 0:
(tiltt,tiltx, tilty, tiltz) = struct.unpack('>4h', buffer(b))
tiltt = 35 + ((tiltt + 13200) / 280.0)
print("{:.1f} {} {} {}".format(tiltt, tiltx, tilty, tiltz))
read += 1
pi.i2c_close(h)
pi.stop()
print()
#End of Joan's ITG3205 script.
#support for storing our values in a config file
import configparser
# for the motor control we need the libraries for this controller:
import os, sys
print(((str(sys.argv[1:])[2:])[:-2]))
if (((str(sys.argv[1:])[2:])[:-2]) == "debug"):
debug = True
else:
debug = False
#read in all our variables
config = configparser.ConfigParser()
config.read("/tools/inputs/masterinputs.txt")
#our latitude
maplat = float(config.get("myvars", "maplat"))
#our longitude
maplon = float(config.get("myvars", "maplon"))
#time limits to keep the robot from doing crazy things
pan_time_limit = int(config.get("myvars", "pan_time_limit"))
tilt_time_limit = int(config.get("myvars", "tilt_time_limit"))
#the lowest angle the IMU and mechanical hardware will reliably support
lowestangle = int(config.get("myvars", "lowestangle"))
#motor speed settings
motor1max_speed = int(config.get("myvars", "motor1max_speed"))
#motor2 is the panning motor
motor2max_speed = int(config.get("myvars", "motor2max_speed"))
#sleep tolerance is the margin by which difference between dawn target and actual heading
#this keeps the robot from moving during the night as the compass shifts
sleep_tolerance = int(config.get("myvars", "sleep_tolerance"))
#This is my magnetic declination *offset*
#If your declination is 11, your offset is -11
MagneticDeclination = float(config.get("myvars", "MagneticDeclination"))
#Calibration of the IMU
HorizontalCalibration = int(config.get("myvars", "HorizontalCalibration"))
AngleOffset = int(config.get("myvars", "AngleOffset"))
#Since the heading can fluctuate, we give a small margin to the compass
#Smaller numbers mean more accurate heading, but motor must go slower
hmargin = int(config.get("myvars", "hmargin"))
#Pololu Motor Stuff
# Set up sequences of motor speeds.
test_forward_speeds = list(range(0, MAX_SPEED, 1)) + [MAX_SPEED] * 200 + list(range(MAX_SPEED, 0, -1)) + [0]
test_reverse_speeds = list(range(0, -MAX_SPEED, -1)) + [-MAX_SPEED] * 200 + list(range(-MAX_SPEED, 0, 1)) + [0]
motors.enable()
motors.setSpeeds(0, 0)
#prep the digital ports
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) #this pin is for the override mode switch
GPIO.setup(19, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) #this pin is for horizon mode, on=do no motor movement at all
GPIO.setup(20, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) #unused but wired
GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) #unused but wired
#These are our global motor speed variables- don't touch
global motor2speed
motor2speed = 0
#Open the serial port for the IMU
#serialport = serial.Serial("/dev/ttyAMA0", 57600, timeout=5)
#Make sure the motors aren't doing anything before we start
motors.setSpeeds(0, 0)
#Calibrate the heading
Declination = MagneticDeclination + HorizontalCalibration
#Give the serial port time to open, so wait 2 seconds
#time.sleep(1)
#Parse the IMU string to get TILT, which we don't really use
#Besides making sure the robot hasn't turned on its side
#Not sure that this formula replacemente is correct yet or not.
def getcurtilt():
curtilt = tiltx
return curtilt
#Parse the IMU string to get HEADING
def getcurheading():
curheading = headingx
return curheading
#Parse the IMU string to get the ANGLE OF INCLINE (forwards/backwards)
#This is what we use for the solar panels, so we have to switch
#from 0 degrees on the normal axis to 0 degrees on the horizon
def getcurangle():
curangle = accelerometerx #Este es un "guess" - todavía no sé si es accelerometría ó qué
return curangle + AngleOffset
#For troubleshooting, we use raw Azimuth from the calc
#Since this is in Azimuth:
# and we need true heading:
# and Azimuth actually is the direction of the shadow, not the sun
from pysolar import solar
def getrawazimuth():
Azimuth = solar.get_azimuth(maplat, maplon, datetime.datetime.utcnow())
return Azimuth
#Convert Azimuth (the direction of the shadow, degrees from south)
# to heading, we have to deal with a few cases
def getsolarheading():
Azimuth = solar.get_azimuth(maplat, maplon, datetime.datetime.utcnow())
if Azimuth < 0:
if (Azimuth >= -180):
solarheading = ((Azimuth * -1) + 180)
if (Azimuth < -180):
solarheading = ((Azimuth * -1) - 180)
if Azimuth >= 0:
solarheading = Azimuth
return solarheading
def tomorrow_heading():
increment_min = 1
incrementeddatetime = 0
tomorrow_corrected = 90
if solar.get_altitude(maplat, maplon, datetime.datetime.utcnow()) < 0:
while solar.get_altitude(maplat, maplon, (datetime.datetime.utcnow() + datetime.timedelta(minutes=incrementeddatetime))) < 0:
incrementeddatetime = incrementeddatetime + increment_min
sunrise_time=(datetime.datetime.utcnow() + datetime.timedelta(minutes=incrementeddatetime))
tomorrow_heading = solar.get_azimuth(maplat, maplon, sunrise_time)
if tomorrow_heading < 0:
if (tomorrow_heading >= -180):
tomorrow_corrected = ((tomorrow_heading * -1) + 180)
if (tomorrow_heading < -180):
tomorrow_corrected = ((tomorrow_heading * -1) - 180)
if tomorrow_heading >= 0:
tomorrow_corrected = tomorrow_heading
return tomorrow_corrected
def getsolarangle(): #to rotate
solarangle = solar.get_altitude(maplat, maplon, datetime.datetime.utcnow())
return solarangle
def motor2neg():
global motor2speed
if (motor2speed < motor2max_speed):
motor2speed = motor2speed + 5
motors.motor2.setSpeed((motor2speed*-1))
return
def motor2backup():
motor2speed = 0
backupsecs = 4
backup_start_time = datetime.datetime.utcnow()
while (datetime.datetime.utcnow() < (backup_start_time + datetime.timedelta(seconds=backupsecs))):
while motor2speed < motor2max_speed:
motor2speed = motor2speed + 1
#Backup
#Doesn't do anything right now
return
def motor2pos():
global motor2speed
if (motor2speed < motor2max_speed):
motor2speed = motor2speed + 5
motors.motor2.setSpeed(motor2speed)
return
tomorrow_static = tomorrow_heading()
#Here we check to make sure horizon (19) and overide (16) digital pins aren't on
#print("GPIO 16 (ovveride) is " + str(GPIO.input(16)))
#print("GPIO 19 (horizon) is " + str(GPIO.input(19)))
#print(GPIO.input(19))
if (GPIO.input(16) == False) and (GPIO.input(19) == False): #check to see if the passive mode switch is on
# GPIO 16 is for override and GPIO 19 is for horizon mode
#In this section we rotate as needed using motor2
starttime = datetime.datetime.utcnow()
if (getcurheading() > getsolarheading()) and (getsolarangle() > 2) and (getcurheading() != 999):
while (getcurheading() > (getsolarheading() + hmargin)) and (starttime + datetime.timedelta(seconds=pan_time_limit) > datetime.datetime.utcnow()):
if debug == True:
print("1: Moving " + str(getcurheading()) + " to " + str(getsolarheading()))
motor2neg()
motors.setSpeeds(0, 0)
starttime = datetime.datetime.utcnow()
if (getcurheading() < getsolarheading()) and (getsolarangle() > 2) and (getcurheading() != 999):
while (getcurheading() < (getsolarheading() - hmargin)) and (starttime + datetime.timedelta(seconds=pan_time_limit) > datetime.datetime.utcnow()):
if debug == True:
print("2: Moving " + str(getcurheading()) + " to " + str(getsolarheading()))
motor2pos()
motors.setSpeeds(0, 0)
starttime = datetime.datetime.utcnow()
if (getcurheading() > tomorrow_static) and (getsolarangle()<0) and (getcurheading() != 999):
if (getcurheading() - tomorrow_static) > sleep_tolerance:
while (getcurheading() > (tomorrow_static + hmargin)) and (starttime + datetime.timedelta(seconds=pan_time_limit) > datetime.datetime.utcnow()):
if debug == True:
print("3: Moving " + str(getcurheading()) + " to " + str(tomorrow_static + hmargin))
motor2neg()
motors.setSpeeds(0, 0)
starttime = datetime.datetime.utcnow()
if (getcurheading() < tomorrow_static) and (getsolarangle()<0) and (getcurheading != 999):
if (tomorrow_static - getcurheading()) > sleep_tolerance:
while (getcurheading() < (tomorrow_static - hmargin)) and (starttime + datetime.timedelta(seconds=pan_time_limit) > datetime.datetime.utcnow()):
if debug == True:
print("4: Moving " + str(getcurheading()) + " to " + str(tomorrow_static + hmargin))
motor2pos()
motors.setSpeeds(0, 0)
#This is horizon mode- if the GPIO switch for pin 19 is flipped
#we lower the panel to 20 degrees. This is good for installing the solar panel,
#since it keeps the robot from moving any more while we're working on it
if (GPIO.input(19) == True) and (GPIO.input(16) == False):
while (getcurangle() > 20):
motor1lower()
motors.setSpeeds(0, 0)
logsolar = open('/tools/inputs/solarvalues.txt','w')
writeline=("[myvars]\n")
logsolar.write(writeline)
writeline=("solar_heading: " + str(round((float(getsolarheading())),1)) + "\n")
logsolar.write(writeline)
writeline=("solar_elevation: " + str(round((float(getsolarangle())),1))+ "\n")
logsolar.write(writeline)
print ("Getcurangle: ", getcurangle())
writeline=("actual_elevation: " + str(round((float(getcurangle())),1))+ "\n")
logsolar.write(writeline)
print ("Getcurheading: ", getcurheading())
writeline=("actual_heading: " + str(round((float(getcurheading())),1))+ "\n")
logsolar.write(writeline)
logsolar.close()
print (datetime.datetime.now(), ",", 'rawazimuth',getrawazimuth(), ",", 'solarheading',getsolarheading(), ",", 'curheading',getcurheading(), ",", 'solarangle',getsolarangle(),",", 'curangle',getcurangle())
motors.setSpeeds(0, 0)
motors.disable()