Giter VIP home page Giter VIP logo

Comments (12)

robert-hh avatar robert-hh commented on August 24, 2024 1

Using GPIO for UART has no reliable timing. The suggestion was to use the PIO state machine, which runs at exact timing. An example for TX is here: https://github.com/raspberrypi/pico-micropython-examples/blob/master/pio/pio_uart_tx.py
You can easily expand that to any bit length. Data is supplied to the state machine by sm.put, which may be a word of up to 32 bit. A parity bit could be added to the bit pattern before pushing them to the state machine. Alternative PIO code for RX canbe found at https://github.com/raspberrypi/pico-examples/blob/master/pio/uart_rx

Even if that is using C code, you can take the PIO script from the uart_rx.pio file.

from micropython.

aomanchuria avatar aomanchuria commented on August 24, 2024 1

I had to play around with the delays 1550 gave me around the correct delay between bytes. 275 gave me around the correct delay between messages.

from micropython.

robert-hh avatar robert-hh commented on August 24, 2024

9 Bit is not supported by the RP2040 MCU. At least an error should be raised. AFAIK, the only port that supports 9 bit is the STM32 port.

from micropython.

aomanchuria avatar aomanchuria commented on August 24, 2024

fantabulous. Do you have some recommended boards from mamazone for this? This is, I'm not kidding, the 4th board I try to get this very simple task done and some how I get one more face smash at the wall. I have a raspberry py zero lying around, do you think that might do it? I'll go see if I can find it in the mean time.

from micropython.

robert-hh avatar robert-hh commented on August 24, 2024

You can get a PyBoard V1.1 from the MicroPython store https://store.micropython.org/product/PYBv1.1
The Adafruit Feather STM32F405 Express should work as well https://www.adafruit.com/product/4382, sold on Amazon as well.
If you search for PyBoard on Amazon, you get links to other STM32F405VG boards, which may work as well with the MicroPython firmware. Only that the board names for the Pins will not match.

from micropython.

Blafy avatar Blafy commented on August 24, 2024

Just bit-bang your serial, with PIO 25000bauds should be fairly doable.

from micropython.

aomanchuria avatar aomanchuria commented on August 24, 2024

this sort of worked:

from machine import Pin
import utime

class UART:
    def __init__(self, tx_pin, baud_rate=2500):
        self.tx_pin = Pin(tx_pin, Pin.OUT)
        self.baud_rate = baud_rate
        self.bit_period_us = int(1000000 / baud_rate)

    def send_data(self, data):
        for byte in data:
            # Start bit
            self.tx_pin.value(0)
            utime.sleep_us(self.bit_period_us)  # Start bit duration

            for _ in range(8):  # 8 data bits
                self.tx_pin.value(byte & 1)
                byte >>= 1
                utime.sleep_us(self.bit_period_us)  # Data bit duration

            # Stop bit
            self.tx_pin.value(1)
            utime.sleep_us(self.bit_period_us)  # Stop bit duration

            # Ensure total byte transmission duration
            utime.sleep_us(self.bit_period_us * 2 - 4)  # Total byte transmission duration

# Example usage:
if __name__ == "__main__":
    uart = UART(tx_pin=8, baud_rate=2500)  # Initialize UART with TX pin connected to GPIO pin 8 and baud rate of 2500
    data = bytearray([102, 104, 0x0F9])  # Data to be transmitted
    uart.send_data(data)  # Send data

from micropython.

aomanchuria avatar aomanchuria commented on August 24, 2024

the timing seems correct:
image

but it doesn't look exactly like the original signal from the projector i'm trying to reverse engineer:
image

from micropython.

aomanchuria avatar aomanchuria commented on August 24, 2024

Over in raspberry pi land, I got this to work but the timing seems really unstable, the waveform looks exactly as it should be but some times the timing is 400us, some times its 530us so you get framing errors:

import pigpio
import time

# Set up GPIO mode
pi = pigpio.pi()  # Use default BCM numbering

# UART settings
BAUD_RATE = 2500  # Change baud rate to 2500 bps
BIT_PERIOD = 400000/ BAUD_RATE  # Time for one bit in microseconds
START_BIT = 0
STOP_BIT = 1
pin = 14

# Data to send
DATA = [
    (0x02, 1),
    (0x04, 1),
    (0xF9, 0)
]

# Function to send a single byte
def send_byte(byte, parity_bit, pin):
    pi.set_mode(pin, pigpio.OUTPUT)

    # Start bit
    pi.write(pin, START_BIT)
    time.sleep(BIT_PERIOD / 1000000)  # Sleep for the bit period in microseconds

    # Data bits
    for i in range(8):
        bit = (byte >> i) & 0x01
        pi.write(pin, bit)
        time.sleep(BIT_PERIOD / 1000000)  # Sleep for the bit period in microseconds

    # Parity bit
    pi.write(pin, parity_bit)
    time.sleep(BIT_PERIOD / 1000000)  # Sleep for the bit period in microseconds

    # Stop bit
    pi.write(pin, STOP_BIT)
    time.sleep(BIT_PERIOD / 1000000)  # Sleep for the bit period in microseconds

try:
    while True:
        # Send data on pins 8, 10, and 27 (BCM numbering)
        #for pin in [14,8, 10, 27]:
        
        for byte, parity_bit in DATA:
            send_byte(byte, parity_bit, pin)
            #time.sleep(0.000681)  # Sleep for the bit period in microseconds
            #time.sleep(0.000450)  # Sleep for the bit period in microseconds
        time.sleep(0.371)  # Sleep for the bit period in microseconds 
except KeyboardInterrupt:
    pass

# Clean up GPIO
pi.stop()

from micropython.

aomanchuria avatar aomanchuria commented on August 24, 2024

Robert-hh, you're so cool! Look I got it to work! its a baby step, I gotta see if the projector actually gets fooled so simply, but man this gives me the tool to replicate the responses the lamp is supposed to give. Thanks for the tip!

from machine import Pin, Timer
from rp2 import PIO, StateMachine, asm_pio

UART_BAUD = 2500
PIN_BASE = 8
NUM_UARTS = 1

# Define the hexadecimal values to be sent
hex_values = [0x102, 0x104, 0x0F9]

# Assembly code for UART transmission
@asm_pio(sideset_init=PIO.OUT_HIGH, out_init=PIO.OUT_HIGH, out_shiftdir=PIO.SHIFT_RIGHT)
def uart_tx():
    # Block with TX deasserted until data available
    pull()
    # Initialise bit counter, assert start bit for 8 cycles
    set(x, 8)  .side(0)       [7]
    # Shift out 9 data bits, 9 execution cycles per bit
    label("bitloop")
    out(pins, 1)              [7]
    jmp(x_dec, "bitloop")
    # Assert stop bit for 8 cycles total (incl 1 for pull())
    nop()      .side(1)       [6]

# Initialize StateMachine for UART
sm = StateMachine(
    0, uart_tx, freq=9 * UART_BAUD, sideset_base=Pin(PIN_BASE), out_base=Pin(PIN_BASE)
)
sm.active(1)

# Function to print the hexadecimal values
def pio_uart_hex(sm, hex_values):
    for hex_val in hex_values:
        sm.put(hex_val)
        # Insert a slight delay between bytes
        for _ in range(1550):  # Adjust this number for the desired delay
            pass

# Print the hexadecimal values from the UART
pio_uart_hex(sm, hex_values)

# Function to repeat the transmission every 200ms
def repeat_send(timer):
    pio_uart_hex(sm, hex_values)

# Initialize timer for repeating transmission
tim = Timer(-1)
tim.init(period=275, mode=Timer.PERIODIC, callback=repeat_send)

image

from micropython.

aomanchuria avatar aomanchuria commented on August 24, 2024

best of all, you plug it and it runs, no 2 minutes booting up delay from a lazy raspberry pi :)

from micropython.

robert-hh avatar robert-hh commented on August 24, 2024

Glad that it works. To be honest, the hint for using PIO came from @Blafy. I just pointed to suitable examples.

from micropython.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.