Get current position of servo with MicroPython on a Raspberry Pi Pico - micropython

I am running MicroPython on a Raspberry Pi Pico. I can set the position of the servo by changing the duty cycles:
from machine import Pin, PWM
servo = PWM(Pin(0))
servo.freq(50)
servo.duty_u16(1350) # sets position to 0 degrees
I may have missed something, but I have read through the docs and couldn't find any way to read the current position of the servo. Is there any way to do this?

Most servos do not provide any sort of position information. You know what the position is because you set it. You can write code that will keep track of this value for you. For example, something like:
from machine import Pin, PWM
class Servo:
min_duty = 40
max_duty = 1115
def __init__(self, pin):
servo = PWM(Pin(pin))
servo.freq(50)
self.servo = servo
self.setpos(90)
def setpos(self, pos):
'''Scale the angular position to a value between self.min_duty
and self.max_duty.'''
if pos < 0 or pos > 180:
raise ValueError(pos)
self.pos = pos
duty = int((pos/180) * (self.max_duty - self.min_duty) + self.min_duty)
self.servo.duty(duty)
You would use the Servo class like this:
>>> s = Servo(18)
>>> s.pos
90
>>> s.setpos(180)
>>> s.pos
180
>>> s.setpos(0)
>>> s.pos
0
>>>
In your question, you have:
servo.duty_u16(1350)
I'm suspicious of this value: at 50Hz, the duty cycle is typically between 40 and 115 (+/1 some small amount at either end), corresponding to ≈ 1ms (duty=40) to 2ms (duty=115).

Related

How do I synchronize clocks on two Raspberry Pi Picos?

I'm sending bits as LED blinks from one Pi Pico, and using another Pico to receive voltage from a photodiode and read the bits.
When sending/receiving from the same PiPico, it works accurately at 60us a bit. However, when sending from one pico and receiving from a second pico, I can only send/receive bits accurately at 0.1s a bit. If I move to sending/receiving at 0.01s, I start losing information. This leads me to believe my issue is with the clocks or sampling rates on the two pipicos, that they are slightly different.
Is there a way to synchronize two pipico clocks using Thonny/Micropython?
Code for Pico #1 sending blinks/bits:
led=Pin(13,Pin.OUT) #Led to blink
SaqVoltage = machine.ADC(28) #receive an input signal, when over a certain voltage, send the time using bits
#Ommitted code here to grab first low voltage values from SaqVoltage signal and use to determine if there is a high voltage received, when high voltage is received, send "hi" in led bits
#More omitted calibration code here for led/photodiode
hi = "0110100001101001"
while True:
SaqVoltage_value = SaqVoltage.read_u16()*3.3 / 65536 #read input signal to see if high voltage is sent
finalBitString = ""
if SaqVoltage_value > saQCutOff: #high voltage found, send "hi" sequence
finalBitString = #hi plus some start/stop sequences
for i in range (0, len(finalBitString)):
if finalBitString[i]=="1":
led(1)
elif finalBitString[i]=="0":
led(0)
utime.sleep(.01)
Code for Pico#2 receiving bits:
SaqDiode = machine.ADC(28) #read photodiode
#ommitted code here to calibrate leds/photodiodes
startSeqSaq = []
wordBits=[]
while True:
utime.sleep(.01) #sample diode every 0.01 seconds
SaqDiode_value = SaqDiode.read_u16()*3.3 / 65536
if (saqDiodeHi - saqCutOff <= SaqDiode_value): #read saq diode and determine 1 or 0
bit=1
elif (SaqDiode_value <= saqDiodeLo + saqCutOff):
bit=0
if len(startSeqSaq)==10: #record last 10 received bits to check if start sequence
startSeqSaq.pop(0)
startSeqSaq.append(bit)
elif len(startSeqSaq)<10:
startSeqSaq.append(bit)
if startSeqSaq == startSeq: #found start sequence, start reading bits
while True:
utime.sleep(.01)
SaqDiode_value = SaqDiode.read_u16()*3.3 / 65536
if (saqDiodeHi - saqCutOff <= SaqDiode_value):
bit=1
wordBits.append(bit)
elif (SaqDiode_value < saqDiodeLo + saqCutOff):
bit=0
wordBits.append(bit)
if len(wordBits)>10: #check for stop sequence
last14=wordBits[-10:]
else:
last14 = []
if last14==endSeq:
char = frombits(wordBits[:-10])
wordBits=[]
print("Function Generator Reset Signal Time in ms from Start: ", char)
break

TypeError: 'id' argument required in Attempting to add NEO M9N to raspbery pi pico

Here is my frankensteined code, the error arises when i'm defining gps_module on line 12. I'm attaching pico pin 4 to the SDA on the GPS, pin 5 to the SCL, ground, and power
from machine import Pin, UART, I2C
#Import utime library to implement delay
import utime, time
sda_pin = machine.Pin(4)
scl_pin = machine.Pin(5)
# Create an I2C object out of our SDA and SCL pin objects
gps_module = machine.I2C(sda=sda_pin, scl=scl_pin)
print(gps_module)
#Used to Store NMEA Sentences
buff = bytearray(255)
TIMEOUT = False
#store the status of satellite is fixed or not
FIX_STATUS = False
Try 1 or 0 in the declaration
gps_module = machine.I2C(1, sda=sda_pin, scl=scl_pin)
https://docs.micropython.org/en/latest/library/machine.I2C.html#constructors
class machine.I2C(id, *, scl, sda, freq=400000)
Construct and return a new I2C object using the following parameters:
id identifies a particular I2C peripheral. Allowed values for depend
on the particular port/board
scl should be a pin object specifying the pin to use for SCL.
sda should be a pin object specifying the pin to use for SDA.
freq should be an integer which sets the maximum frequency for SCL.

Analog control Raspberry pi using pyPS4Controller

I have a Raspberry Pi with a robotic kit and I would like to control it using a PS4 controller but using analog input. I have successfully connected the controller and I can read events and program the motors to answer binary input. The documentation (pyPS4Controller), however, is not explicit about using analog values (Ex: 50% press on R2 outputs 0.5 forward).
Could someone please help me figure out how to make this?
Thanks in advance!
# This is the example for binary buttons
from pyPS4Controller.controller import Controller
class MyController(Controller):
def __init__(self, **kwargs):
Controller.__init__(self, **kwargs)
def on_x_press(self):
print("Forward")
def on_x_release(self):
print("Stop")
# --> The objective is having some way to capture the "intensity" of the button press to use the motors accordingly
controller = MyController(interface="/dev/input/js0", connecting_using_ds4drv=False)
controller.listen()
After some tweaking and trial and error I ended up finding a solution.
The analog functions receive an input called value containing the analog value of the input given to the controller.
from pyPS4Controller.controller import Controller
from gpiozero import CamJamKitRobot as camjam
# Translate controller input into motor output values
def transf(raw):
temp = (raw+32767)/65534
# Filter values that are too weak for the motors to move
if abs(temp) < 0.25:
return 0
# Return a value between 0.3 and 1.0
else:
return round(temp, 1)
class MyController(Controller):
def __init__(self, **kwargs):
Controller.__init__(self, **kwargs)
self.robot = camjam()
def on_R2_press(self, value):
# 'value' becomes 0 or a float between 0.3 and 1.0
value = transf(value)
self.robot.value = (value, value)
print(f"R2 {value}")
def on_R2_release(self):
self.robot.value = (0,0)
print(f"R2 FREE")
def on_L2_press(self, value):
# 'value' becomes 0 or a float between -1.0 and -0.3
value = -transf(value)
self.robot.value = (value, value)
print(f"L2 {value}")
def on_L2_release(self):
self.robot.value = (0,0)
print(f"L2 FREE")
# Press OPTIONS (=START) to stop and exit
def on_options_press(self):
print("\nExiting (START)")
self.robot.value = (0,0)
exit(1)
controller = MyController(interface="/dev/input/js0", connecting_using_ds4drv=False)
controller.listen()

Micropython error : OSError: [Errno 19] ENODEV

I am trying to use pressure sensors and a LOLIN D32 pro microcontroller to measure water level. The two pressure sensors are MS5803 and BME280 below is my code
'''
import machine
from machine import Pin, I2C
import bme280, ms5803
import time
i2c= I2C(scl=Pin(22), sda=Pin(21), freq=10000)
bme1 = bme280.BME280(i2c=i2c, address = 119)
BuiltinLED = machine.Pin(5, Pin.OUT)
BuiltinLED.value(1)
WaterLevelDifference=0
def depth():
[T1,P1,H1] = bme1.raw_values #T in degrees C, P in hPa
[P2,T2] = ms5803.read(i2c=i2c, address = 118)
WaterLevelDifference = ((P2-P1)*100/9810)
return WaterLevelDifference
depth()
while WaterLevelDifference<100:
if WaterLevelDifference > 0.1:
BuiltinLED.value(0) #turns LED on
else:
depth()
time.sleep(0.5)
print(WaterLevelDifference)
'''
I have done i2c.scan() and it shows [118,119] but sometimes intermittently. What does this error mean?

Raspberry Pi PWM control becomes affected when I combine it with FLASK

Im trying to implement a control using Raspberry Pi's PWM. I had success controlling the intensity of a LED with the following code:
# Pin Definitons:
pwmPin = 18 # Broadcom pin 18 (P1 pin 12)
# Pin Setup:
GPIO.setmode(GPIO.BCM) # Broadcom pin-numbering scheme
GPIO.setup(pwmPin, GPIO.OUT) # PWM pin set as output
pwm = GPIO.PWM(pwmPin, 50) # Initialize PWM on pwmPin 100Hz frequency
# Initial state for LEDs:
pwm.start(10)
try:
while 1:
cycle = raw_input("Introduce Duty Cycle")
dc = int(cycle)
pwm.ChangeDutyCycle(dc)
except KeyboardInterrupt: # If CTRL+C is pressed, exit cleanly:
pwm.stop() # stop PWM
GPIO.cleanup() # cleanup all GPIO
Then I wanted to control the LED brightness through a web page. For that I used FLASK and the previous code. When I set the Duty Cycle from the web page the LED brightness change accordingly but it fluctuates randomly.
It's a strange behavior and I dont know why it is happening. Right here the code implemented on FLASK:
# Pin Definitons:
pwmPin = 18 # Broadcom pin 18 (P1 pin 12)
# Pin Setup:
GPIO.setmode(GPIO.BCM) # Broadcom pin-numbering scheme
GPIO.setup(pwmPin, GPIO.OUT) # PWM pin set as output
pwm = GPIO.PWM(pwmPin, 50) # Initialize PWM on pwmPin 100Hz frequency
# Initial state for LEDs:
pwm.start(10)
app = Flask(__name__)
#app.route('/')
def index():
return render_template('motor.html')
#app.route('/motor', methods=['POST'])
def motor():
dc = int(request.form['valor'])
pwm.ChangeDutyCycle(dc)
return redirect(url_for('index'))
if __name__ == "__main__":
app.run(host='0.0.0.0', port=81, debug=True)
pwm.stop() # stop PWM
GPIO.cleanup() # cleanup all GPIO