I was on travel this weekend and tested the Tire Pressure Monitoring System (TPMS) project on the long road trip. The sensitivity of the receiver is not what it needs to be to pickup all four tires. Previously I was able to pickup the signal from all four tires with a longer antenna, however during this trip only two tires seemed to be received consistently while the other ones would only be received once in a while, but most of the time were not received at all.
I suspect that the reason for the difference may be due to the tires being rotated and the two older sensors may be in the rear, and further away from the receiver or it may be that the placement of the receiver was different enough to cause the signal to not be heard. I plan on digging into this a bit more but will continue to focus on rewriting the code for the TPMS project then attempt to resolve the issue with signal strength. It may simply be that the configuration of the radio needs to be adjusted to improve the gain of the received signal.
Testing projects in real world situations can help uncover issues that we wish would have been discovered earlier. One such example was with my Speech Timer Project.
I traveled to Binghamton, NY so I could attend my family reunion and decided to arrive early to attend the Morning Knights Toastmasters meeting in-person. I brought along my Speech Timer to try it out at the meeting. Before the meeting even started, I ran into an issue. The clock connects to the internet to get the time to set the real time clock (RTC). I knew this but thought the clock would still operate as the RTC does not need to be set for the speech timer to work. The configuration is set for my home network so I knew it would not connect to the internet at the meeting location. I pressed the button on the remote to activate the timer function and nothing happened. I ended up tucking the clock back into my backpack. I’ll need to edit the code and run some tests to make absolutely certain that it will work when it cannot connect to the internet.
This lesson shows how important it is to test our projects in a variety of situations. I believe I have tested this scenario before, so I will need to make certain that I can recreate it with the current code base, then move on from there.
Apple Vision Pro user (Image from Trusted Reviews)
I read an article today titled, “I Know What the Apple Vision Pro Is For” in the New York Magazine. It was very interesting seeing how the Apple Vision Pro (AVP) is making a difference in the lives of people with disabilities. I find it amazing that Apple was able to make the device so accessible but see why they were able to be successful. They still have some work to do as the article points out but they have done a great job with the device.
Apple was able to be successful because they have developers on the team, who themselves have disabilities. This provides a few advantages for producing something that is accessible. First off, the developers have first hand knowledge of what will work and what will not. It is like having the business owner writing code or making design choices. Secondly is developers, who do not have disabilities can get near instant feedback.
I have not had the opportunity to work with someone who has a disability. I have worked with one individual many years ago, who I believe had oculocutaneous albinism, just as Maxine Collard, in the story. I recall that they had a jewelers loop and would get right up to the Cathode Ray Tube (CRT) monitor to see the screen. I guess that made the article a bit more special to me as I saw their struggles first hand and can imagine Maxine Collard’s interactions with the computer and other challenges she faces.
Getting near instant feedback is important to writing better code and really for doing anything well. I recall the first time that I worked on a project where the development team needed to write unit tests for the code that we were writing and coupled with DevOps and automated testing. It was a powerful combination. I was able to check in code and tell within a few minutes if the code was going to break the build or not. It was great when the code did not break the build but when it did, it was great to know it right away so the code was still fresh in my head. I did not need to get back into the mindset that I was in a week or two ago. Getting back in the mindset and remembering what you were doing when you wrote the code, why you made the design choices you did takes away valuable time that could be used to code the next chunk of functionality. I was so impressed by the time saving and the empowerment that near instant feedback gave me. I built a small device to show me the status of the builds.
Information Radiator for Jenkins DevOps Builds
The near instant feedback gave some additional benefit to the project team as well. It did not eliminate defects, but it did result in fewer easy to find bugs. I did increase development time but the added benefits I feel outweighed the additional development effort and given enough time, would actually reduce development time as the developers would improve over time.
The immediate benefits is the code would be more robust, particularly around data input validation and business rule checks. Testers can write code to test these things but it takes a great deal of time to test various combinations of data inputs, edge cases, and requested business rule behaviors. Unit tests and the execution of those tests when a developer checks in code catches most of the issues that can arise from these cases.
Additionally as I started getting use to the instant feedback, I found that I was checking in code more frequently and was more comfortable in breaking code and user stories into smaller pieces. The reason for this I believe is two fold. Firstly there is gratification in seeing that code is checked in and passes tests as it is working as expected. Secondly, there is greater confidence that I change something that may impact some other functionality as I can be somewhat confident that if the code will break anything else, I will know it once the code is checked in.
While the article was on accessibility, I think there were some other things to learn as well. Getting near instant feedback is a great path to creating something that is reliable and works as intended. You can still develop code that no one uses, but it will be quality code. If you want code that users will find is useful, you need to get usability feedback as soon as possible from the community that will be using the software. Apple is a great example by including people with disabilities on their development teams.
I have started to rewrite the code based on the analysis of the parameters and timings. I have yet to look across the code for the various TPMS sensors to see if they use common code. I suspect that they do, but if they don’t it may make the approach impractical. I plan to investigate loading the parameters and timing values from files on the SD Card as well. I think the file approach may lead to a more sustainable approach.
The code rewrite starts with a structure, CC1101_Parameters, to hold the timing parameters and CC1101_Settings, to hold the settings for the CC1101 radio. The default values specified in the structures are the most common values for each property.
struct CC1101_Parameters {
int expectedbitcount = 72;
int expectedbytecount = 9;
int expectedfifobytecount = 21;
int syncbits = 16;
int cdwidth_min = 5500;
int cdwidth_max = 11500;
int shorttiming_min = 35;
int shorttiming_nom = 50;
int shorttiming_max = 79;
int longtiming_min = 80;
int longtiming_max = 120;
int synctiming_min = 175;
int synctiming_max = 1200;
int endtiming_min = 0;
int endtiming_max = 500;
}; // CC1101_Parameters
struct CC1101_Settings {
byte cc1101_defval_iocfg2 = 0x0C; // GDO2 Output Pin Configuration - Serial out (synchronous)
byte cc1101_defval_iocfg1 = 0x2E; // GDO1 Output Pin Configuration - not used
byte cc1101_defval_iocfg0 = 0x0E; // GDO0 Output Pin Configuration - Carrier Sense output
byte cc1101_defval_fifothr = 0x0F; // RX FIFO and TX FIFO Thresholds - 64 bytes in FIFO
byte cc1101_defval_sync1 = 0xD5; // Synchronization word, high byte 11010101 01001111
byte cc1101_defval_sync0 = 0x4F; // Synchronization word, low byte
byte cc1101_defval_pktlen = 0x09; // Packet Length
byte cc1101_defval_pktctrl1 = 0x00; // Packet Automation Control
byte cc1101_defval_pktctrl0 = 0x12; // Packet Automation Control - synchronous data
byte cc1101_defval_addr = 0x00; // Device Address
byte cc1101_defval_channr = 0x00; // Channel Number
byte cc1101_defval_fsctrl1 = 0x0F; // Frequency Synthesizer Control
byte cc1101_defval_fsctrl0 = 0x00; // Frequency Synthesizer Control
byte cc1101_defval_freq2 = 0x10; // Frequency Control Word, High Byte
byte cc1101_defval_freq1 = 0xB0; // Frequency Control Word, Middle Byte
byte cc1101_defval_freq0 = 0x71; // Frequency Control Word, Low Byte
byte cc1101_defval_deviatn = 0x40; // Modem Deviation Setting (+/-25.390625kHz)
byte cc1101_defval_mdmcfg4 = 0x59; // Modem Configuration (59 = data rate = 20kHz, RX bw 325kHz)
byte cc1101_defval_mdmcfg3 = 0x93; // Modem Configuration (now 93 = data rate = 20kHz)
byte cc1101_defval_mdmcfg2 = 0x10; // Modem Configuration (GFSK, No Sync or Manchester coding)
byte cc1101_defval_mdmcfg1 = 0x21; // Modem Configuration Channel spacing 100kHz
byte cc1101_defval_mdmcfg0 = 0xF8; // Modem Configuration
byte cc1101_defval_agcctrl2 = 0x87; // AGC Control
byte cc1101_defval_agcctrl1 = 0x58; // AGC Control
byte cc1101_defval_agcctrl0 = 0x80; // AGC Control
byte cc1101_defval_mcsm2 = 0x07; // Main Radio Control State Machine Configuration
byte cc1101_defval_mcsm1 = 0x3C; // Main Radio Control State Machine Configuration
byte cc1101_defval_mcsm0 = 0x18; // Main Radio Control State Machine Configuration
byte cc1101_defval_foccfg = 0x16; // Frequency Offset Compensation Configuration
byte cc1101_defval_bscfg = 0x6C; // Bit Synchronization Configuration
byte cc1101_defval_worevt1 = 0x87; // High Byte Event0 Timeout
byte cc1101_defval_worevt0 = 0x6B; // Low Byte Event0 Timeout
byte cc1101_defval_worctrl = 0xFB; // Wake On Radio Control
byte cc1101_defval_frend1 = 0x56; // Front End RX Configuration
byte cc1101_defval_frend0 = 0x10; // Front End TX Configuration
byte cc1101_defval_fscal3 = 0xE9; // Frequency Synthesizer Calibration
byte cc1101_defval_fscal2 = 0x2A; // Frequency Synthesizer Calibration
byte cc1101_defval_fscal1 = 0x00; // Frequency Synthesizer Calibration
byte cc1101_defval_fscal0 = 0x1F; // Frequency Synthesizer Calibration
byte cc1101_defval_rcctrl1 = 0x41; // RC Oscillator Configuration
byte cc1101_defval_rcctrl0 = 0x00; // RC Oscillator Configuration
byte cc1101_defval_fstest = 0x59; // Frequency Synthesizer Calibration Control
byte cc1101_defval_ptest = 0x7F; // Production Test
byte cc1101_defval_agctest = 0x3F; // AGC Test
byte cc1101_defval_test2 = 0x81; // Various Test Settings
byte cc1101_defval_test1 = 0x35; // Various Test Settings
byte cc1101_defval_test0 = 0x09; // Various Test Settings
}; // CC1101_Settings
The next bit of code makes use of switch case statements to set the values based on the selected configuration.
void cc1101_init_vars() {
switch (carSettings.freq) {
case TPMS_Frequencies::UK_433MHz:
switch (carSettings.tpmsSensorType) {
case TPMS_Sensors::Citroen:
cc1101_parameters.expectedbitcount = 88;
cc1101_parameters.expectedbytecount = 10;
cc1101_parameters.cdwidth_min = 8000;
break;
case TPMS_Sensors::Dacia:
cc1101_parameters.cdwidth_min = 7000;
cc1101_settings.cc1101_defval_freq0 = 0x0C;
cc1101_settings.cc1101_defval_deviatn = 0x41;
break;
case TPMS_Sensors::Ford:
cc1101_parameters.expectedbitcount = 64;
cc1101_parameters.expectedbytecount = 8;
cc1101_parameters.cdwidth_max = 10000;
break;
case TPMS_Sensors::Hyundai_i35:
cc1101_parameters.expectedbitcount = 64;
cc1101_parameters.expectedbytecount = 8;
cc1101_parameters.cdwidth_max = 9000;
cc1101_parameters.synctiming_min = 140;
cc1101_parameters.synctiming_max = 160;
break;
// ...
case TPMS_Sensors::Zoe:
cc1101_parameters.expectedbitcount = 64;
cc1101_parameters.expectedbytecount = 8;
cc1101_parameters.cdwidth_min = 7000;
cc1101_settings.cc1101_defval_freq0 = 0x0C;
cc1101_settings.cc1101_defval_deviatn = 0x41;
break;
default:
break;
}
break;
case TPMS_Frequencies::US_315MHz:
switch (carSettings.tpmsSensorType) {
case TPMS_Sensors::Citroen:
// UK 433 MHz Only
break;
case TPMS_Sensors::Dacia:
// UK 433 MHz Only
break;
case TPMS_Sensors::Ford:
cc1101_parameters.expectedbitcount = 64;
cc1101_parameters.expectedbytecount = 8;
cc1101_parameters.cdwidth_max = 10000;
cc1101_settings.cc1101_defval_freq2 = 0x0C;
cc1101_settings.cc1101_defval_freq1 = 0x1D;
cc1101_settings.cc1101_defval_freq0 = 0x57;
break;
case TPMS_Sensors::Hyundai_i35:
cc1101_parameters.expectedbitcount = 64;
cc1101_parameters.expectedbytecount = 8;
cc1101_parameters.cdwidth_max = 9000;
cc1101_parameters.synctiming_min = 140;
cc1101_parameters.synctiming_max = 160;
cc1101_settings.cc1101_defval_freq2 = 0x0C;
cc1101_settings.cc1101_defval_freq1 = 0x1D;
cc1101_settings.cc1101_defval_freq0 = 0x57;
break;
// ...
case TPMS_Sensors::Toyota_TRW_C070:
cc1101_parameters.expectedbitcount = 64;
cc1101_parameters.expectedbytecount = 8;
cc1101_parameters.cdwidth_max = 9000;
cc1101_parameters.synctiming_min = 140;
cc1101_parameters.synctiming_max = 160;
cc1101_settings.cc1101_defval_freq2 = 0x0C;
cc1101_settings.cc1101_defval_freq1 = 0x1D;
cc1101_settings.cc1101_defval_freq0 = 0x57;
break;
case TPMS_Sensors::TruckSolar:
// UK 433 MHz Only
break;
case TPMS_Sensors::Zoe:
// UK 433 MHz Only
break;
default:
break;
}
break;
default:
break;
}
}
The next step is to determine if common code can be written for receiving the data from each brand of TPMS sensor.
Another month has gone by and I am still working on the Speech Timer project. I was able to develop a solution with CircuitPython but was not happy with the end product. Perhaps it would be possible to get to a more stable version but even with all the RAM available on the Raspberry Pi Pico W, I would still run into issues with the heap becoming fragmented and not having enough free space to allocate additional space to server web pages reliably. I tried many of the tips to resolve the issue including calling garbage collection periodically. These changes helped the code run a bit longer but still ran into issues. I decided to rewrite the code in C++, using the Arduino IDE and wanted to be able to debug my code on the Raspberry Pi Pico while it was running as I ran into an issue when I changed the configuration to disable serial debugging output by not calling Serial.begin().
I made a Picoprobe and attempted to debug my code, but things were not as straight forward as they could have been, which resulted in many hours waisted.
I had followed the instructions in the getting-started-with-pico.pdf guide and used the Windows Pico SDK, but could not get debugging to work in Visual Code or the Arduino IDE. I was nearly ready to setup another PC with Linux and give that a go as I had seen folks saw that just works with no issues. I’m running Windows, which I assumed was part of the issue. I saw another Windows user who was very frustrated as well and stating that it seemed they were the only ones testing/using this in Windows. They eventually got it working although they could not figure out the root cause. Unfortunately I too got it working and have no clear indication of what the root issue was but I have an idea that there is an issue with the Windows setup scripts that needs to be addressed. If someone has Visual Code and/or Arduino IDE installed before installing the SDK, they will have issues. This may not be the fault of the SDK, it could be with the Visual Code and Arduino IDE setup but I suspect it is indeed the Pico SDK setup on Windows that is the issue.
Out of frustration, I reinstalled the Windows Pico SDK and checked Visual Code and the Arduino IDE. Magically, Visual Studio code worked but the Arduino IDE still failed. I then uninstalled the Arduino IDE, then restarted the PC. Once the PC restarted, I deleted the C:\Users\<user id>\AppData\Local\Arduino15 and C:\Program Files\Arduino IDE folders to clear out anything that was already configured. I then reinstalled the Arduino IDE and tried again and the Arduino IDE worked too.
There really is a problem with the Pico SDK but it will be difficult to fix unless someone can figure out what changed from the problem install and the fixed install. Unfortunately, I did not capture anything before so I cannot tell what went wrong.
In the end, once debugging was working, I was able to step through my code and found the issue in about 2 minutes. Too bad the debugging fiasco caused several days of wasted time trying to get the debugging working.
Just wanted to drop a quick update as I have not been able to post for the past few weeks. I am working on a couple of projects that I plan to write about shortly.
Speech Timer Clock
I have been working on a speech timer clock for my Toastmasters Club. I took an alpha version to a club meeting to get some feedback and took the feedback and have been making improvements to it. Below is a quick video showing a little of the clock’s operation.
Speech timer showing demo of 1 to 2 minute speech
Artificial Intelligence (AI)
I looked into CodeProject.AI Server and found it very easy to use and useful. I plan to write some examples and corrected examples that are posted on CodeProject website. I have started a GitHub Repository for the examples at https://github.com/richteel/AI_Sample.
Wiring diagram for Raspberry Pi boards connected to LilyGo T-Beam devices
In this part of the Meshtastic with Raspberry Pi (Serial) series, we will be writing some code to test the connection, then adding to our code to send sample data. When sending data, we will format the message to allow us to reject data if it is not formatted correctly and do some simple error detection.
On the Raspberry Pi, open a terminal window or use PuTTY to run the following command. sudo nano /boot/cmdline.txt
Comment out or delete the “console=serial0,115400” in the line.
Once the cmdline.txt has been modified, restart the Raspberry Pi.
NOTES: If the console=serial0,115400 is missing, you skipped enabling the serial port from the raspi-config tool. Look back at the earlier posts in this series for instructions on how to enable the serial port. It is also possible that the baud rate in the command is something other than 115400 so you may see a different baud rate, which is fine, but you will need to remove that argument from the file.
Test Program
Now that the serial port is properly configured, we can write a simple program and test the T-Beam connection to the Raspberry Pi. On both Raspberry Pi boards, create a uart.py file with the following code.
'''
UART communication on Raspberry Pi using Python
http://www.electronicwings.com
'''
import serial
from time import sleep
ser = serial.Serial ("/dev/ttyS0", 38400) #Open port with baud rate
while True:
raw_data = ser.read() #read serial port
sleep(0.03)
if raw_data:
data_len = ser.inWaiting()
raw_data += ser.read(data_len) #read serial port
received_data = str(raw_data, "utf-8")
print (received_data) #print received data
The code will listen for data on the serial port and will print the received data in the terminal window. Run the code on both Raspberry Pi boards by typing the following command. sudo python uart.py
On the Android device, open the Meshtastic application and type a message and press the send button.
The message will be displayed in the terminal window of the receiving Raspberry Pi device.
Sample code sending and receiving data
Before using the following example, it is suggested to change the serial configuration to “Simple” and creating an additional channel named “serial”. Screenshots were taken of the Meshtastic application and placed into a Google Album. Refer to the album if you have any questions regarding what configuration values were used for this example.
The sample code will send CPU Temperature data twice per minute. Below are a few notes/requirements.
The data will be sent as JSON.
The data will be contained in a Python Dictionary with string values for the keys. Sample keys:
t: Time in UTC ISO 8601 format without milliseconds
nam: The host name of the Raspberry Pi
cput: CPU Temperature in degrees Celsius
Float values will be sent as formatted strings with the precession required for the application. As an example, temperature will be sent with two decimal values.
The total length of the message shall not exceed 200 bytes. In practice, it should be kept well below 200 bytes. This requires that the keys for the key value pairs to be kept short.
Example Code:
The following example code was written to meet the above requirements.
'''
- References -
--------------
ISO 8601
https://pynative.com/python-iso-8601-datetime/
UART communication on Raspberry Pi using Pyhton
http://www.electronicwings.com
'''
import serial
import time
from datetime import datetime, timezone
import re
import socket
import json
def get_temp():
with open('/sys/class/thermal/thermal_zone0/temp', 'r') as infile:
return float(infile.read()) * 1e-3
# Open port with baud rate
ser = serial.Serial("/dev/ttyS0", 38400)
# Set the start time in the past so that the first data point will be sent at the startF
start = time.time() - 600
# Create a variable for the received data.
received_data = ""
# Flag for knowning if the error for T-Beam being disconnected has been displayed
no_serial = False
try:
while True:
data_len = 0
data_len = ser.in_waiting
utc_dt = datetime.now(timezone.utc).replace(microsecond=0)
if data_len > 0:
raw_data = ser.read(data_len) # read serial port
try:
received_data += str(raw_data, "utf-8")
x = re.search("\{.*\}", received_data)
if x:
# PuTTY changes tab characters to spaces so we will use the pipe symbol
# print(F"{utc_dt.isoformat()}\tRECV\t{x[0]}")
print(F"{utc_dt.isoformat()}|RECV|{x[0]}")
received_data = ""
if no_serial:
no_serial = False
except UnicodeDecodeError:
received_data = ""
if not no_serial:
print("ERROR: The serial connection may be down")
no_serial = True
if time.time() - start > 30:
start = time.time()
temp = get_temp()
dat = {
"t": utc_dt.isoformat(),
"nam": socket.gethostname(),
"cput": F"{temp:0.2f}",
}
if len(json.dumps(dat)) < 200:
ser.write(bytes(json.dumps(dat), "utf-8"))
# PuTTY changes tab characters to spaces so we will use the pipe symbol
# print(F"{utc_dt.isoformat()}\tSENT\t{json.dumps(dat)}")
print(F"{utc_dt.isoformat()}|SENT|{json.dumps(dat)}")
else:
print(
F"ERROR: Data length is greater than 200 bytes (length={len(json.dumps(dat))})")
except KeyboardInterrupt:
print("\r\nExiting")
# finally:
# GPIO.cleanup()
Below is the output from both Raspberry Pi boards running the code with the same T-Beam Meshtastic settings.
An Excel workbook was put together to check the delay from transmit and receive as well as identifying packets being received out of order. Previous runs with slightly different code did contain out of order packets so it should not be assumed that packets will be received in order. Below is the Check.xlsx file that you may download.
Below are some statistics from the Check.xlsx Excel Workbook with data produced from 27 minutes runtime of the sample code.
pi-sensor01
Receive Delay (hh:mm:ss)
Min: 00:00:07
Max: 00:04:12
Average: 00:01:28
Median: 00:00:57
Data Received out of order: 0
Data Points
Total: 104
Sent: 56
Received: 48
Sent Packets Received by pi-sensor01:
Received: 55
Not Received: 1
Percent of Packets Received: 98.21%
pi-sensor02
Receive Delay (hh:mm:ss)
Min: 00:00:07
Max: 00:01:35
Average: 00:00:23
Median: 00:00:15
Data Received out of order: 1
Data Points
Total: 111
Sent: 56
Received: 55
Sent Packets Received by pi-sensor01:
Received: 48
Not Received: 8
Percent of Packets Received: 85.71%
Going Further
This is the end of this series at least for now. It was put together to provide some information with one way to send data between two Raspberry Pi devices using serial communications. There are other ways to send data using the serial port. One of the more interesting ways may be using the PROTO mode for the Meshtastic serial port. It looks like using the PROTO mode may allow for the code to setup and configure the Meshtastic device. If that is the case, it may provide much more control and standardization across connections. (Meshtastic Serial Port Configuration)
Another area to look into is how to improve the successful delivery of messages in a timely manor. It may be sending messages every 30 seconds was too fast and flooded the available channels. It may also be possible that the store and forward setting was misunderstood and caused message flooding on the channel. The devices may have been too close together to provide reliable communications. All of these things and others could be looked into to see if it is possible to create more reliable communications.
Wiring diagram for Raspberry Pi boards connected to LilyGo T-Beam devices
In this part of the Meshtastic with Raspberry Pi (Serial) series, we will be installing Meshtastic to the LilyGo T-Beam devices. We will then create a Meshtastic Channel on one LilyGo T-Beam and replicate the channel to the other LilyGo T-Beam. We will then wire the Raspberry Pi and LilyGo T-Beam devices.
Install Meshtastic Firmware on the LilyGo T-Beam devices
Firmware Version: Select the latest version. NOTE: May want to install latest beta version if you want the most stable version available.
Update or reinstall: Either option is fine. A reinstall may wipe out any settings that you have configured on the device but may be the best option for the first installation.
Click the “CONNECT” button
Select the serial port that the T-Beam is connected to. If you are uncertain, you may open the Windows Device Manager and look at Ports (COM & LPT), then look for “USB-Enhanced-SERIAL CH9102” or similar device to find the serial port.
Click “INSTALL TBEAM”
Click “INSTALL”
You will see the progress as it installs the firmware.
When the installation is complete, click “NEXT”
You may then click the X in the device dashboard to close the dashboard.
Repeat the steps for the other T-Beam, then close the browser.
Configure T-Beam and Create Channel
Using a mobile phone, tablet, or PC, open the Meshtastic App or Web Client. The following examples will show the Web Client and Android App.
It is best to use the Android application to configure the T-Beam device. The instructions provided here for the Web Browser are incomplete as I could not determine how to set some of the options that I know are available in the Android Application. These instructions are provided to demonstrate how to access the configuration from the web browser.
With the LilyGo T-Beam connected to the PC, open a browser and navigate to https://client.meshtastic.org/. Click the “New Connection” button.
The “Connect New Device” dialog is shown. Click the “New device” button.
Select the T-Beam device from the list of devices and click the “Connect” button.
Click the device from the device list.
The selected device will turn gray to show that it is selected. Click the X in the top right corner of the “Connect New Device” dialog to close the dialog box.
Android App
If the Meshtastic application is not already installed, go to the Play Store and search for an install the Meshtastic App.
Open the Meshtastic Application and click the gear icon in the top toolbar on the right, then click the “+” in the lower right corner to add a new Meshtastic device.
On the T-Beam device, look for the device name on the LCD screen.
In the Meshtastic App, select the device name that matches the name on the T-Beam LCD Screen, in the list of available devices.
The T-Beam device will display a Bluetooth pin on the LCD Screen.
Enter the Pin in the Bluetooth pairing request screen and click “OK”.
Next, we need to set the region by clicking on the region dropdown. NOTE: Make certain that the correct device is selected.
Select your region from the list. My region is “US”, so that is what I selected.
The selected region will be displayed in the application and the T-Beam device will reboot.
Once the device reboots, you may enter a name if you like. Do not move off this screen right away or the name may not stick. You may find that you need to reenter the name a few times before it is saved.
Click on the hamburger menu in the upper right corner and select “Radio configuration”.
Click on “Serial” from the “Radio configuration” menu.
Enter the settings for the Serial Port, then click the “Send” button.
Serial enabled: Turn on
RX: Pin 13
TX: Pin 14
Serial baud rate: Selected 38400 baud but may select different rate. Make certain this matches when writing code on the Raspberry Pi.
Serial mode: TEXTMSG
If you want a private channel, setup the channel on one device, then scan the QR Code on the other devices in the Mesh. I will not go over setting up a channel. For more information on setting up a channel, go to Meshtastic’s Channel Configuration page.
Wire Everything Up
The connection between the Raspberry Pi and the T-Beam device only requires three wires. A wire for the ground and two for the serial connection. The serial connection will cross the transmit (TX) and receive (RX) wires so that the TX from the Raspberry Pi is connected to the T-Beam RX and the Raspberry Pi RX will connect to the T-Beam TX. Below is a diagram showing these connections.
Wiring diagram for Raspberry Pi board connected to LilyGo T-Beam device
Wiring diagram for Raspberry Pi boards connected to LilyGo T-Beam devices
In Part I, we installed the Raspberry Pi OS and connected to the Raspberry Pi using PuTTY and VNC from another PC. In Part II, we will install Visual Code on the Raspberry Pi to allow us to code directly on the Raspberry Pi using a modern IDE.
It is not required to install Visual Studio Code. There are several options for writing programs and running them on the Raspberry Pi. It is possible to simply use the Text Editor on the desktop, Nano or VI from the terminal, or use an editor on the PC and transfer files using WinSCP.
Installing Visual Studio Code
The first thing to note is that the Chromium web browser is not going to work well on older Raspberry Pi boards. I am using a Raspberry Pi 3, so it is necessary to open a terminal and run the following command to launch the Dillo web browser: dillo
Clicking on the .deb Arm32 link does nothing as the link is using JavaScript to download the correct file. We will need to get the installation package from our PC and move it to the Raspberry Pi.
On the PC, navigate to https://code.visualstudio.com/download and click the .deb Arm32 link to download the installation package. Save it to a known location and remember where you saved it.
Open WinSCP and connect to the Raspberry Pi.
If it is the first time connecting to the Raspberry Pi, you will see a Warning dialog. Click “Yes” to continue.
Once connected, in the right pane of the WinSCP application, navigate to the desktop folder on the Raspberry Pi and in the left pane, navigate to the location of Visual Studio Code installation package on your PC. Once the locations have been selected, you may click and drag the installation package from the PC to the Raspberry Pi.
Once the package has been transferred, switch to VNC Viewer and you will see the file on your desktop.
Right-click on the installation package and select “Package Install” from the context menu.
Once the installation completes, you may launch Visual Studio Code from the menu by navigating to Programming > Visual Studio Code.
NOTE: You may delete the Visual Studio Code installer from the desktop if you wish.
I like to use the Explorer, the top icon on the left toolbar, to open a folder. From there, I may create files and folders for the project. In the screenshot below, I have created a folder named “Test” in my home folder and added a file named “test.py”. Once I created the file, Visual Studio Code recognized that I created a Python file and prompted me to install the Python language extension.
Wiring diagram for Raspberry Pi boards connected to LilyGo T-Beam devices
In this post, I will step through getting Linux installed on a Raspberry Pi with an overview of different installations, and detailed setup on a headless installation. I will then move into connecting the Raspberry Pi to a LilyGo T-Beam device with Meshtastic Firmware, with the connection to the Raspberry Pi using a Serial Connection. Connecting one or more sensors to the Raspberry Pi, and finally sending that data to another Raspberry Pi connected to a LilyGo T-Beam.
Before Installing Linux on Raspberry Pi
There are several options for installing Linux on the Raspberry Pi. The first question to answer is, which distribution to use? There are several different distributions available for the Raspberry Pi boards. A comprehensive list of distributions available may be found at https://elinux.org/RPi_Distributions. The distribution that I will be using is Raspberry Pi OS by Raspberry Pi.
The next question to answer is do we want a desktop or do we wish to run in headless mode? Installing a desktop is helpful if we wish to use the Raspberry Pi as a regular computer with a nice user interface. Installing a desktop does require more resources but makes the Raspberry Pi more useful if we wish to connect it to a display and keyboard or use VNC from another machine.
A headless mode installation is best if we only need to work from the terminal (command line) and/or we want more resources for running applications to monitor sensors or server up web pages or application program interfaces (API).
The last question to ask is what peripherals and options do we need to have configured? We know we will want the serial interface enabled, since that will be used to communicate to the LilyGo T-Beam devices. Depending on the sensors that we wish to use, we may want to enable the I2C interface.
Another option we will want is to be able to control the Raspberry Pi from another machine as we do not want to connect a monitor, keyboard, and mouse. We will need to enable SSH and VNC to allow control from another machine.
Below is a list of our installation options that we will configure.
Distribution: Raspberry Pi OS
Mode: Desktop
Enable SSH
Enable VNC
Enable Serial
Enable I2C
We have a couple of ways to enable the above configuration but we will configure all of these options from the Raspberry Pi Imager as it makes this relatively easy and quick. The toughest part is determining what the IP Address is of the Raspberry Pi when it boots up.
Required software on the Windows, Linux, or Apple PC
There is some software that we need to have on the PC in order to install the Raspberry Pi OS and control it from the PC. If the listed software does not support your operating system, look for a similar application for your operating system.
Insert an SD Card in your PC and note the drive letter. Make certain that the SD Card does not have anything that you wish to keep as the card will be wiped, so your information will be gone.
Open the Raspberry Pi OS Imager and click the “Choose OS” button In Windows, you will be prompted by the User Account Control (UAC) to continue. Select “Yes”
Select “Raspberry Pi OS (32-bit)
Click the button in the lower right corner, with the gear icon for the advanced settings
Set the hostname (optional but recommended)
Make certain that “Enable SSH” is checked and “Use password authentication” is selected
Change the password and optionally change the username
Enter the settings for your WiFi connection if not using ethernet
Optionally set time zone and keyboard layout
Once the options have been set, click the “Save” button
Click the “Choose Storage” button
Select the SD Card identified earlier. Make certain that this is the SD Card as all data will be wiped from the selected drive and will not be able to be recovered.
Click the “Write” button to write the OS image to the SD Card
If you are absolutely certain that the correct SD Card has been selected and there is no data on the card that you wish to keep, click the “Yes” button.
Once the image has been written to the SD Card, you may click the “Continue” button, close the Raspberry Pi OS Imager, and remove the SD Card from the PC, and insert it into the Raspberry Pi.
Once the SD Card is inserted into the Raspberry Pi, connect power to the Raspberry Pi
After a couple of minutes, open PuTTY on your PC and attempt to connect to the Raspberry Pi using the name provided in the advanced options of the Raspberry Pi OS Imager. In the example, “pi-sensor01.local” was used. In PuTTY, attempt to connect using the hostname provided in the image configuration. NOTE: If configuring another Raspberry Pi, do not use the same hostname.
Click the “Open” button after entering the hostname
You may see a PuTTY Security Alert if it is the first time connecting to the Raspberry Pi. If so, click the “Accept” button.
Once connected, enter the username and password that was entered in the advanced settings fo the the Raspberry Pi OS Imager.
Open the Raspberry Pi Configuration Tool by entering the following command: sudo raspi-config
Select option 3, Interface Options, and press the Enter key
Select option I3, VNC, and press the Enter key
Select Yes, to enable VNC Server, and press the Enter key
Select OK, and press the Enter key
Repeat the steps above to enable the Serial Port and any other interfaces, such as SPI and I2C that may be needed.
Check if there are any other options that you may want to set or execute. Some useful options are Advanced Options > Expand Filesystem and Update.
When done making changes, select Finish to exit the configuration tool.
If you selected Expand Filesystem, you may want to restart the Raspberry Pi by issuing the following command: sudo reboot now
VNC Viewer
Check that we are able to connect the Raspberry Pi Desktop using VNC Viewer.
Open VNC Viewer and connect to the hostname for the Raspberry Pi
If this is the first time you are connecting the Raspberry Pi, you will see an Identity Check dialog. Click the “Continue” button.
Enter the Raspberry Pi username and password, then click the “OK” button.
If everything went correctly, you will be presented with the Raspberry Pi desktop.
You must be logged in to post a comment.