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

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

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.

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

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).

Grove I2C display not working on Raspberry Pi 3B

I only have my RPi 3B and a I²C display, I don't own any GrovePi hat and I want to show some text to the said display. Is there a way to make it work?
My display.
i2cdetect -y 1 shows this result, meaning the RPi is detecting the I²C display and it should work. But nothing seemed to be showing on the display, except for the full block on the first row.
I've tried literally everything on the internet, some library worked (as in throwing no errors) but the display still stays the same, full block on the first row.
I've installed python3, smbus, smbus2 and i2c-tools. I've changed the address to 3e.
My most recent *.py file. It does write 'LCD printing' yet nothing else works.
I don't find a way to change the contrast of the LCD (no potentiometer or whatsoever)
#!/usr/bin/python3
import smbus2 as smbus
import time
# Define some device parameters
I2C_ADDR = 0x3e # I2C device address, if any error, change this address to 0x3f
LCD_WIDTH = 16 # Maximum characters per line
# Define some device constants
LCD_CHR = 1 # Mode - Sending data
LCD_CMD = 0 # Mode - Sending command
LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line
LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line
LCD_BACKLIGHT = 0x08 # On
ENABLE = 0b00000100 # Enable bit
# Timing constants
E_PULSE = 0.0005
E_DELAY = 0.0005
# Open I2C interface
# bus = smbus.SMBus(0) # Rev 1 Pi uses 0
bus = smbus.SMBus(1) # Rev 2 Pi uses 1
def lcd_init():
# Initialise display
lcd_byte(0x33, LCD_CMD) # 110011 Initialise
lcd_byte(0x32, LCD_CMD) # 110010 Initialise
lcd_byte(0x06, LCD_CMD) # 000110 Cursor move direction
lcd_byte(0x0C, LCD_CMD) # 001100 Display On,Cursor Off, Blink Off
lcd_byte(0x28, LCD_CMD) # 101000 Data length, number of lines, font size
lcd_byte(0x01, LCD_CMD) # 000001 Clear display
time.sleep(E_DELAY)
def lcd_byte(bits, mode):
# Send byte to data pins
# bits = the data
# mode = 1 for data
# 0 for command
bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
bits_low = mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT
# High bits
bus.write_byte(I2C_ADDR, bits_high)
lcd_toggle_enable(bits_high)
# Low bits
bus.write_byte(I2C_ADDR, bits_low)
lcd_toggle_enable(bits_low)
def lcd_toggle_enable(bits):
# Toggle enable
time.sleep(E_DELAY)
bus.write_byte(I2C_ADDR, (bits | ENABLE))
time.sleep(E_PULSE)
bus.write_byte(I2C_ADDR, (bits & ~ENABLE))
time.sleep(E_DELAY)
def lcd_string(message, line):
# Send string to display
message = message.ljust(LCD_WIDTH, " ")
lcd_byte(line, LCD_CMD)
for i in range(LCD_WIDTH):
lcd_byte(ord(message[i]), LCD_CHR)
if __name__ == '__main__':
lcd_init()
while True:
# Send some test
lcd_string("Hello ", LCD_LINE_1)
lcd_string(" World", LCD_LINE_2)
print('LCD printing!')
time.sleep(3)

Hardware interrupt between Raspberry pi and Atmega 328

I have connected my RPI and atmega328 together in order to control the start of an event on my arduino. In order to do so, GPIO 25 (RPI) is connected directly to pin7 (Arduino PD7). I've got a python script on the RPI witch set the GPIO 25 to high then back to LOW:
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.OUT)
GPIO.output(25, 1)
#Do some stuff
GPIO.output(25, 0)
The arduino is waiting in a loop for either a physical button to be pressed or the pin7 to be set to HIGH by the RPI:
const int interrupt = 7;
const int button = 13;
const int led = 9;
void setup() {
Serial.begin(9600);
pinMode(interrupt, INPUT);
pinMode(button,INPUT);
pinMode(led, OUTPUT);
digitalWrite(led, LOW);
}
void loop() {
bool on = false;
bool buttonOn = false;
while (!on || !buttonOn) {
on = digitalRead(interrupt);
buttonOn = digitalRead(button);
digitalWrite(led, LOW);
}
digitalWrite(led, HIGH);
delay(1000);
}
Now unfortunately this doesn't work. I have checked the logic level of the atmega328 (https://learn.sparkfun.com/tutorials/logic-levels) and it seems that 3.3V is good enough for HIGH signal.
Am I missing something with the pull up /pull down resistance? I know the PD7 on the atmega is specified as follow:
Port D is an 8-bit bi-directional I/O port with internal pull-up
resistors (selected for each bit). The Port D output buffers have
symmetrical drive characteristics with both high sink and source
capability. As inputs, Port D pins that are externally pulled low will
source current if the pull-up resistors are activated. The Port D pins
are tristated when a reset condition becomes active, even if the clock
is not running.
EDIT:
I have done more testing and I am getting the HIGH or LOW value correctly. It seems that the issue comes from the:
while ((!on) || (!buttonOn)) {
Is there an issue with Arduino and the OR operator in a while loop? Even when one condition is true and the other one is false, it never goes out of the loop.
while ((!on) || (!buttonOn)) {
}
That loop will run as long as one of the variables is false.
Yesterday I was for some reason thinking that you were reading the interrupt pin twice when reading your code.
3.3 v output should be ok to turn the Arduino input high.
You can have a wiring problem or your raspberry pi can be so fast that the arduino misses the pulse.
Change your program on the raspberry pi to leave the output high for so long (e.g. 10) seconds that you can measure it with a multimeter to see that you are setting the right pin.
Does the Arduino now see the input?