How do I format the time in micropython? - time

I'm prototyping using a Raspberry, Pi Pico and Micropython, and I am trying to convert the time.localtime() to a format that's more readable and in the form of a string. I've tried .join() and a few other things but because the Pico runs on Micropython, I can't find a solution.
here is my Python code:
from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
now = time.localtime()
print("Current date and time: ")
print(now)
w = 128
h = 32
i2c = I2C(0, scl=Pin(17), sda=Pin(16), freq=200000)
addr = i2c.scan()[0]
oled = SSD1306_I2C(w, h, i2c, addr)
oled.fill(0)
oled.text("Raspberry Pi ", 5, 5)
olex.text("Hi Leo", 5, 15)
oled.show()

import time
now = time.localtime()
print("Date: {}/{}/{}".format(now[1], now[2], now[0]))
print("Time: {}:{}".format(now[3], now[4]))
Your variable now has all required data- it consis of tuple
(year, month, mday, hour, minute, second, weekday, yearday)
Documentation available here

Related

Having trouble with comparing datetimes, when there are DB, Golang and Unix versions

So, basically a person has a shift, with a start time and duration, and I need to know how many minutes to go.
I retrieve from the database (mySQL) a standard string of datetime for the start of the shift (eg. 2022-01-01 09:00:00)
I also retrieve the number of hours of the shift (eg. 8)
I can then determine current time, using Golang's Time.time, but this format is different.
Please see code below, which explains the problem better, and gives the pieces missing.
Thanks!
var shiftStartDB string // For example 2022-01-01 09:00:00
var shiftStartUnix int // For example, start time converted to minutes since epoch
var offTimer int // Number of hours for the shift
var shiftEndDB string // For example 2022-01-01 17:00:00
var shiftEndUnix int // For example, end time converted to minutes since epoch
var nowTime Time.time // Golangs version of time for now
var nowUnix int // Golang now converted to Unix time
var templateID string
var minsToGo int
_ = db.QueryRow("SELECT LastSignedOn, OffTimer, TemplateID FROM assets WHERE ID = ?", assetid).Scan(&shiftStartDB, &offTimer, &templateID)
shiftStartUnix = <convert database time into unix time>
if offTimerTemp == 0 {
_ = db.QueryRow("OffTimer FROM templates WHERE ID = ?", templateID).Scan(&offTimer)
}
shiftEndUnix = shiftStartUnix + (offTimer * 60)
nowTime = time.Now()
nowUnix = <convert golang time into unix time>
minsToGo = shiftEndInt - nowInt
You can use nowUnix = nowTime.UNIX()/60, as Time.UNIX returns the number of seconds elapsed since epoch. that said, this might be easier to deal with if you parsed the times and used go library time functions directly:
shiftStartTime,err := time.Parse("2006-02-01 15:04:05",dbTime)
shiftEnd=shiftStartTime.Add(time.Hour*offTimer)
minsToGo:=shiftEnd.Sub(time.Now()).Minutes()

ESP32 crashes with Micropython with simple test program

Here is a simple Micropython program that I wrote to test my ESP32 Vroom32 board. It crashes after several minutes. I got about 38000 counts out of it.
from time import sleep
n = 0
while 1:
print(n)
n += 1
sleep(0.02)
Here is the code that I'm using to read it.
import serial, serial.tools.list_ports
import time
def find_port(): #Finds which port the arduino is plugged into
ports = list(serial.tools.list_ports.comports())
for p in ports:
if "EA60" in p[2]:
return(p[0])
usbport = find_port()
ser = serial.Serial(usbport, 115200) #setup serial
while 1:
try:
data = ser.readline()
ser.flushInput()
data = data.strip().decode()
print(data)
time.sleep(0.02)
except Exception as e:
print(e)
I've tried different things such as blinking the LED and slowing down the timing to 0.2 seconds. After doing those two things it ran about 8 hours and then crashed. When it crashed. I had to unplug the device and plug it back in and restart the python program on the computer before it would run again. Simply resetting the device did not work. Also, after I added the LED blink code (not included in the above example) the LED kept blinking the entire time. It was like it was still running, but not communicating.
New micropython code that blinks:
from time import sleep
from machine import Pin
n = 0
led = Pin(2, Pin.OUT)
while 1:
print(n)
n += 1
led.value(not led.value())
sleep(0.2)
Update:
Last night I added some code to try to catch the error. The board still crashed and no error file was created.
New main.py
from time import sleep
from machine import Pin
n = 0
led = Pin(2, Pin.OUT)
while 1:
try:
led.value(not led.value())
n += 1
print(n)
sleep(0.2)
except Exception as e:
print("ESP32: ", e)
New desktop script:
import serial, serial.tools.list_ports
import time
def find_port(): #Finds which port the arduino is plugged into
ports = list(serial.tools.list_ports.comports())
for p in ports:
if "EA60" in p[2]:
return(p[0])
usbport = find_port()
ser = serial.Serial(usbport, 115200, timeout=10) #setup serial
while 1:
try:
data = ser.readline()
ser.flushInput()
data = data.strip().decode()
print(data)
if "ESP32" in data:
with open("errors.txt", "a") as f:
err = data + "\n"
f.write(err)
time.sleep(0.2)
except Exception as e:
print(e)

NodeMCU - enable UART1/2 on ESP32

I've build firmware as described here: https://nodemcu.readthedocs.io/en/dev-esp32/build/
But I cannot get hardware UART 1 or 2 working. Is there any particular component that has to be enabled (and it's not enabled by default) in order to get it working?
here is my test code:
uart_id = 2
local function on_data(data)
print("IN: ", tostring(data))
end
local function on_error(data)
print("ERR: ", tostring(data))
end
local cnt = 0;
local function on_timer()
print(". "..cnt)
cnt = cnt + 1
uart.write(uart_id, "# " .. cnt .. "\n")
end
local tmrObj = tmr.create()
tmrObj:register(5000, tmr.ALARM_AUTO, on_timer)
tmrObj:start()
uart.setup(uart_id, 115200, 8, uart.PARITY_NONE, uart.STOPBITS_1, 1)
uart.on(uart_id, "data", '\r', on_data)
uart.on(uart_id, "error", on_error)
uart.setmode(uart_id, uart.MODE_UART)
uart.start(uart_id)
Firmware is OK, uart.setup was incorrect. PINs were missing, and for some reason default PINs did not work, this one is fine:
uart.setup(uart_id, 115200, 8, uart.PARITY_NONE, uart.STOPBITS_1, {rx = 16, tx = 17})

Zero cross detection with serial communication from Arduino to Raspberry Pi

I'm new at python and i'm setting up my school project that it's going to detect the zero cross for trigger a PWM pulse so i'm using Arduino and Raspberry Pi 3.
I'm trying to read from serial port of the Arduino for read it in the Raspberry Pi, after that what i need is build an if conditional with that data that i recieved.
Arduino sends from serial port ON and OFF message with this code
const int inputPin = 2;
int value = 0;
void setup() {
Serial.begin(9600);
pinMode(inputPin, INPUT_PULLUP);
}
void loop(){
value = digitalRead(inputPin); //digital read of pin
//sends a message to serial port depending of the value read
if (value == HIGH) {
Serial.println("ON");
}
else {
Serial.println("OFF");
}
delayMicroseconds(1000);
}
On Arduino serial read it shows continuously
OFF
ON
ON
ON
OFF
So on python i want to read those two values "ON" and "OFF" or at least one that when it takes a OFF value for example at the next 1 ms it turn on PWM pulse.
Something like:
if zerocross == OFF:
pi.hardware_PWM(heat,200,dutycycle)
This is my python code for read the data from serial port:
import time
try:
import serial
arduino = serial.Serial('/dev/ttyACM0', baudrate=9600, timeout=1.0)
arduino.setDTR(False)
time.sleep(1)
arduino.flushInput()
arduino.setDTR(True)
except (ImportError, serial.SerialException):
import io
class FakeArduino(io.RawIOBase):
def readline(self):
time.sleep(0.1)
return b'sensor = 0\toutput = 0\r\n'
arduino = FakeArduino()
with arduino:
while True:
try:
line = arduino.readline()
zerocross = line.decode('ascii', errors='replace')#, end=''
if zerocross == OFF:
print ('ok')
except KeyboardInterrupt:
print("Exiting")
break
this is the out in the python shell
Traceback (most recent call last):
File "/home/pi/Desktop/arduino python raspb.py", line 33, in <module>
if zerocross == OFF:
NameError: name 'OFF' is not defined
I've already tried to convert the serial data into a string but i get "built-in method decode" when i try to print the value. Please if someone can show me some other methods i would appreciate it so much.

Write byte to Arduino from Ruby over serial

I'm trying to send an integer over the serial port to my Ardunio. The chip is then going to display the number in binary on the LED's. However I'm having lots of trouble trying to send the data as a byte over the serial port, as far as I can debug the following code sends it as the ASC char values.
Can anyone point me in the right direction or spot the mistake? I'd really appreciate it. I've been pulling my hair out over this for a long time.
Ruby
require 'rubygems'
require 'serialport' # use Kernel::require on windows, works better.
#params for serial port
port_str = "/dev/tty.usbserial-A700dZt3" #may be different for you
baud_rate = 9600
data_bits = 8
stop_bits = 1
parity = SerialPort::NONE
sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity)
i = 15
#just write forever
while true do
sp.write(i.to_s(2))
sleep 10
end
Arduino
int ledPin = 10;
int ledPin1 = 11;
int ledPin2 = 12;
int ledPin3 = 13;
byte incomingByte; // for incoming serial data
void setup() {
pinMode(ledPin, OUTPUT); // initialize the LED pin as an output:
pinMode(ledPin1, OUTPUT); // initialize the LED pin as an output:
pinMode(ledPin2, OUTPUT); // initialize the LED pin as an output:
pinMode(ledPin3, OUTPUT); // initialize the LED pin as an output:
Serial.begin(9600);
Serial.println("I am online");
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0) {
incomingByte = Serial.read();
Serial.println(incomingByte, DEC);
int value = (incomingByte, DEC) % 16;
digitalWrite(ledPin, (value >> 0) % 2);
digitalWrite(ledPin1, (value >> 1) % 2);
digitalWrite(ledPin2, (value >> 2) % 2);
digitalWrite(ledPin3, (value >> 3) % 2); // MSB
}
}
I'm guessing you are trying to write the value 15 in order to light all the LEDs at once. However, 15.to_s(2) is "1111". The ASCII value of the character '1' is 49, so instead of writing 15 once you are writing 49 four times in rapid succession.
The write command you are looking for is therefore probably sp.putc(i). This writes only one character with the given binary value (= machine-readable for Arduino) instead of an ASCII string representation of the value expressed in binary (= human-readable for you).
So keeping everything else the same, replace the while loop in your Ruby code with:
loop do
sp.putc(i)
puts 'Wrote: %d = %bb' % [ i, i ]
i = (i == 15) ? 0 : (i + 1)
sleep(10)
end
If you wish to read the responses from Arduino, you can use e.g. sp.gets to get one line of text, e.g. try placing puts 'Arduino replied: ' + sp.gets in the loop before sleep (and one puts sp.gets before the loop to read the "I am online" sent when the connection is first established).
Edit: I just spotted another problem in your code, on the Arduino side: value = (incomingByte, DEC) % 16; always results in the value 10 because (incomingByte, DEC) has the value DEC (which is 10). You should use value = incomingByte % 16; instead. Or do away with value altogether and modify incomingByte itself, e.g. incomingByte %= 16;.
Your problems may be caused by buffering. To disable buffering, you can do one of the following:
Set sp to unbuffered after creating it (before writing): sp.sync = true
Call flush after the write
Use the unbuffered syswrite instead of write
It's been so long since I did anything with serial ports that I can't help there, but I do see one thing.
>> 15.to_s #=> "15"
and
>> 15.to_s(2) #=> "1111"
I think if you want the binary value to be sent you'll want "\xf" or "\u000F".
Change your code from:
while true do
sp.write(i.to_s(2)) # <-- this sends a multi-character ASCII representation of the "i" value, NOT the binary.
sleep 10
end
to:
while true do
sp.write(i.chr) # <-- this sends a single byte binary representation of the "i" value, NOT the ASCII.
sleep 10
end
To show the difference, here's the length of the strings being output:
>> 15.to_s(2).size #=> 4
>> 15.chr.size #=> 1
And the decimal values of the bytes comprising the strings:
>> 15.to_s(2).bytes.to_a #=> [49, 49, 49, 49]
>> 15.chr.bytes.to_a #=> [15]
I've had this Ruby code work before
while true do
printf("%c", sp.getc)
end
rather than using sp.write(i.to_s). It looks like you are explicitly converting it to a string, which may be the cause of your problems.
I found the original blog post I used:
http://www.arduino.cc/playground/Interfacing/Ruby

Resources