|
| 1 | +--- |
| 2 | +title: Serial communication (UART) |
| 3 | +description: Learn how to use UART with Micropython |
| 4 | +author: Pedro Sousa Lima |
| 5 | +--- |
| 6 | + |
| 7 | +Universal Asynchronous Receiver-Transmitter, or **UART**, is one of the simplest and most widely used communication protocols for connecting devices. It enables point-to-point communication over just two wires, making it a perfect fit for debugging, logging, and connecting to peripheral devices. |
| 8 | + |
| 9 | +## How UART Works |
| 10 | + |
| 11 | +UART communication relies on: |
| 12 | +- **TX (Transmit):** Sends data from one device to another. |
| 13 | +- **RX (Receive):** Receives data from the transmitting device. |
| 14 | + |
| 15 | +Unlike other protocols like I2C or SPI, UART is asynchronous, meaning it doesn’t use a clock line. Instead, the sender and receiver agree on a common data rate (baud rate), such as 9600 bits per second. |
| 16 | + |
| 17 | +Each device directly connects TX to RX and RX to TX. |
| 18 | +### Key Features of UART |
| 19 | + |
| 20 | +1. **Simple Point-to-Point Communication:** Ideal for connecting two devices. |
| 21 | +2. **Flexible Speeds:** Baud rates can be adjusted to meet application needs. |
| 22 | +3. **Independent Lines:** TX and RX operate independently, enabling bidirectional communication. |
| 23 | + |
| 24 | +## How to Read the Output |
| 25 | + |
| 26 | +To observe the output of your UART communication, you’ll need a secondary board (or a USB-to-UART adapter) to act as a receiver. Here’s how you can set it up: |
| 27 | + |
| 28 | +1. **Primary Board (Transmitter):** Runs the main UART code examples provided below. |
| 29 | +2. **Secondary Board (Receiver):** Reads from the UART interface and displays the output on a serial monitor like Arduino IDE or PuTTY. |
| 30 | + |
| 31 | +### Circuit Setup |
| 32 | +- Connect the **TX1 (GPIO43)** of the primary board to the **RX** of the secondary board. |
| 33 | +- Connect the **RX1 (GPIO44)** of the primary board to the **TX** of the secondary board. |
| 34 | +- Connect the ground (GND) of both devices together. |
| 35 | + |
| 36 | + |
| 37 | + |
| 38 | +### Code for Secondary Board |
| 39 | +The board simply forwards received UART data to its serial monitor. Use the following code: |
| 40 | + |
| 41 | +```python |
| 42 | +from machine import UART |
| 43 | + |
| 44 | +# Initialize UART |
| 45 | +uart = UART(1, baudrate=9600, tx=43, rx=44) # Adjust TX/RX pins as needed |
| 46 | + |
| 47 | +while True: |
| 48 | + if uart.any(): # Check if data is available |
| 49 | + ch = uart.read(1).decode() # Read one character |
| 50 | + print(ch, end="") # Print to the console |
| 51 | +``` |
| 52 | + |
| 53 | +1. Flash the above code to the secondary board. |
| 54 | +2. Open a serial monitor for the secondary board (e.g., Arduino Lab for Micropython, Arduino IDE Serial Monitor, Putty). |
| 55 | + |
| 56 | + |
| 57 | +## Example 1: Testing UART |
| 58 | + |
| 59 | +In this first example, we’ll create a program that prints `UART says Hi!` every second, allowing you to verify that the UART connection is working. |
| 60 | + |
| 61 | +### Circuit Diagram |
| 62 | +For this example: |
| 63 | +- **Connect TX1 (GPIO43)** to the RX of your receiving device (e.g., USB-to-serial adapter). |
| 64 | +- **Connect RX1 (GPIO44)** to the TX of your receiving device. |
| 65 | +- **Connect GND** to the ground of the receiving device. |
| 66 | + |
| 67 | + |
| 68 | +### Code Example |
| 69 | + |
| 70 | +Copy the following code into your `main.py` file and run it on the board you designated as "primary": |
| 71 | + |
| 72 | +```python |
| 73 | +from machine import UART, Timer |
| 74 | + |
| 75 | +# Initialize UART |
| 76 | +uart = UART(1, baudrate=9600, tx=43, rx=44) |
| 77 | + |
| 78 | +# Timer to send debug message |
| 79 | +def send_debug_message(timer): |
| 80 | + uart.write("UART says Hi!\n") |
| 81 | + |
| 82 | +# Configure the timer |
| 83 | +timer = Timer(0) |
| 84 | +timer.init(period=1000, mode=Timer.PERIODIC, callback=send_debug_message) |
| 85 | + |
| 86 | +# Keep the program running |
| 87 | +while True: |
| 88 | + pass |
| 89 | +``` |
| 90 | + |
| 91 | +### Expected Output |
| 92 | +When connected to a serial monitor, you should see: |
| 93 | + |
| 94 | +``` |
| 95 | +UART says Hi! |
| 96 | +UART says Hi! |
| 97 | +UART says Hi! |
| 98 | +``` |
| 99 | + |
| 100 | + |
| 101 | +If you don’t see this output, check your connections and ensure the baud rate matches. |
| 102 | + |
| 103 | +## Example 2: Ping-Pong Communication |
| 104 | + |
| 105 | +Next, let’s make the device respond with `pong` when it receives the message `ping`. This demonstrates how to handle incoming UART messages. |
| 106 | + |
| 107 | +### Circuit Diagram |
| 108 | +Use the same circuit as before. Ensure TX, RX, and GND are properly connected. |
| 109 | + |
| 110 | +### Code Example |
| 111 | + |
| 112 | +Copy the following code into your `main.py` file and run it on the board you designated as "primary": |
| 113 | + |
| 114 | +```python |
| 115 | +from machine import UART |
| 116 | + |
| 117 | +# Initialize UART |
| 118 | +uart = UART(1, baudrate=9600, tx=43, rx=44) |
| 119 | + |
| 120 | +buffer = "" |
| 121 | + |
| 122 | +while True: |
| 123 | + if uart.any(): # Check if data is available |
| 124 | + ch = uart.read(1).decode() # Read one character |
| 125 | + uart.write(ch) # Echo the input |
| 126 | + buffer += ch |
| 127 | + |
| 128 | + if ch == '\n': # End of message |
| 129 | + if buffer.strip().lower() == "ping": |
| 130 | + uart.write("pong\n") |
| 131 | + buffer = "" # Clear the buffer |
| 132 | +``` |
| 133 | +Now copy the following code into your `main.py` file and run it on the board you designated as "secondary". In this case we are expanding the secondary board to be able to write via UART too: |
| 134 | + |
| 135 | +```python |
| 136 | +from machine import UART |
| 137 | +import sys |
| 138 | +import |
| 139 | + |
| 140 | +# Initialize UART |
| 141 | +uart = UART(1, baudrate=9600, tx=43, rx=44) # Adjust TX/RX pins as needed |
| 142 | + |
| 143 | +while True: |
| 144 | + # Check if there's data coming from UART |
| 145 | + if uart.any(): |
| 146 | + ch = uart.read(1).decode() # Read one character from UART |
| 147 | + print(ch, end="") # Print to USB serial monitor |
| 148 | + |
| 149 | + # Check if there's data enselecttered in REPL |
| 150 | + if sys.stdin in select.select([sys.stdin], [], [], 0)[0]: |
| 151 | + input_text = sys.stdin.read().strip() # Read user input |
| 152 | + uart.write(input_text + "\n") # Send via UART |
| 153 | +``` |
| 154 | + |
| 155 | +### Expected Output |
| 156 | +1. Type `ping` followed by `Enter` in your serial monitor. |
| 157 | +2. You should see: |
| 158 | + ``` |
| 159 | + pong |
| 160 | + ``` |
| 161 | + |
| 162 | +Any other input will simply be echoed back to the sender. |
| 163 | + |
0 commit comments