Category: Projects Related to Palm OS PDAs
Published on: 2022-02-04
After connecting a microcontroller to a Palm m100, I had the idea to bring some data to the Palm via the microcontroller's Wi-Fi interface.
The m100 can "talk" PPP, so the most ideal solution would be a PPP-Server on the D1 mini.
There are some projects on GitHub that achieve this in some way, but I wasn't able to get any of them running:
Maybe in the future, I can dig into one of these projects and modify them to access the internet directly from the Palm over the D1 mini. For now, I was looking for an easier solution.
Instead of overthinking everything, I received advice from a Discord user to take a few steps back and begin small.
The new goal was to bring the m100 online via a wired serial connection to a Linux machine.
This isn't hard since you only need a few commands. I did this on Ubuntu 20.04 LTS, but it should work similarly on other distributions:
First, you need to know the name of the Ethernet device and the local IP.
The output of
ifconfig -a
is helpful, which looks like this:
user@thinkCentre:~$ ifconfig -a enp0s31f6: flags=4163 mtu 1500 inet 192.168.0.234 netmask 255.255.255.0 broadcast 192.168.0.255 ether 60:20:99:0a:d5:90 txqueuelen 1000 (Ethernet) RX packets 659970 bytes 774014055 (774.0 MB) RX errors 0 dropped 5278 overruns 0 frame 0 TX packets 213892 bytes 32920680 (32.9 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 17 memory 0xf7100000-f7120000 lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10 loop txqueuelen 1000 (Lokale Schleife) RX packets 5316 bytes 595665 (595.6 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 5316 bytes 595665 (595.6 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Since I don't have Wi-Fi or any other related interfaces on my machine, it was relatively easy to identify the right one:
enp0s31f6
But even with more interfaces, there should only be one with an IPv4 inet address.
The needed local address in my case is:
192.168.0.234
This script executes the required iptables commands and at the end, the actual pppd command, which establishes the connection to the m100:
#!/bin/bash echo 1 > /proc/sys/net/ipv4/ip_forward iptables -A INPUT ! -i enp0s31f6 -j ACCEPT iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -t nat -A POSTROUTING -o enp0s31f6 -j MASQUERADE /usr/sbin/pppd ttyUSB0 9600 local noauth 192.168.0.234:192.168.0.77 ms-dns 192.168.0.71 passive updetach asyncmap 0
In the first, second, and fourth iptables commands, the interface name ("enp0s31f6") needs to be replaced.
Also, in the pppd command, all IP addresses need to be replaced:
"ttyUSB0" is the interface from the Linux machine to the Palm. I used a serial-to-USB cable, so it shows up in
sudo dmesg
as "ttyUSB0" after the adapter was plugged into the PC:
[ 7501.198317] usb 1-1.3: new full-speed USB device number 8 using xhci_hcd [ 7501.403471] usb 1-1.3: New USB device found, idVendor=067b, idProduct=2303, bcdDevice= 4.00 [ 7501.403484] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [ 7501.403489] usb 1-1.3: Product: USB-Serial Controller D [ 7501.403494] usb 1-1.3: Manufacturer: Prolific Technology Inc. [ 7501.478405] usbcore: registered new interface driver usbserial_generic [ 7501.478430] usbserial: USB Serial support registered for generic [ 7501.482783] usbcore: registered new interface driver pl2303 [ 7501.482809] usbserial: USB Serial support registered for pl2303 [ 7501.482853] pl2303 1-1.3:1.0: pl2303 converter detected [ 7501.484300] usb 1-1.3: pl2303 converter now attached to ttyUSB0 [ 7502.117843] kauditd_printk_skb: 86 callbacks suppressed
(Second line from bottom shows the needed port name, "ttyUSB0".)
When the script is running, it is waiting for a connection:
user@thinkCentre:~/Desktop$ sudo bash palm-ppp.sh Using interface ppp0 Connect: ppp0 <--> /dev/ttyUSB0
Before a connection can be established, some configuration needs to be done on the m100.
First, in "Preferences," select "Connection":
Here, we need to add a new configuration as shown:
The name can be anything, but in "Details..." the Speed needs to be set to "9.600 bps". It is possible to use more when using a wire, but later we are stuck with 9600 bps.
At the end, it should look like this:
Next, select "Network" in the Preferences menu:
The "Service name" can be anything. The User Name is blank and the Password needs to be shown as "-Prompt-". Connection, the last point, is our newly created configuration:
The (Network) "Details..." look like this:
And the "Script..." is just "End:":
Now, everything is set up. The m100 is connected via the serial cable to the Linux machine via a serial-to-USB adapter cable, "palm-ppp.sh" is running, and shows "Connect: ppp0 <--> /dev/ttyUSB0".
After hitting "Connect," the connection will be established, as shown here:
When it is established, a few pixels should flash in the upper right corner of the m100 and the "Connect" button now shows "Disconnect":
The connection was successful and "Xiino" or "EudoraWeb" can be used to surf the internet. But beware of two facts:
The next step was to replace the serial cable with a wireless solution, which should look like this:
Palm (Serial) <=> ESP8266 <=> Wi-Fi <=> Router <=> Wi-Fi <=> ESP8266 <=> Serial-USB-Adapter <=> Linux-Machine with pppd
As mentioned before, this isn't the most optimal/elegant solution, but it is a solution to bring internet wirelessly to the Palm m100.
It requires a pppd server, which is always on when the m100 wants to go online. But since it can be run on a Raspberry Pi, it is acceptable.
Since the Palm is already configured for an internet connection, and the pppd is running, we just need to replace the serial cable.
On the Palm side, the already installed D1 mini is used for the serial-to-Wi-Fi bridge and on the other side, an ESP8266 (NodeMCU V3) is used for the Wi-Fi-to-serial bridge.
So just the code for the D1 mini on the m100 (secondary) and the ESP8266, which will be connected to the Linux machine (main) is needed.
The code for the ESP8266 looks like this:
#include #include const char *ssid = "MySSID"; const char *pw = "MySecurePassword"; #define BAUDRATE 9600 #define TCP_PORT 8880 WiFiServer server(TCP_PORT); WiFiClient tcpClient; uint16_t dataCounter = 0; int roundCounterS = 0; int roundCounterT = 0; void setup() { delay(500); Serial.begin(BAUDRATE); WiFi.mode(WIFI_STA); WiFi.begin(ssid, pw); while (WiFi.status() != WL_CONNECTED) { delay(500); } server.begin(); // start TCP server server.setNoDelay(true); } void loop() { if(!server.hasClient() && !tcpClient.connected()){ while(!server.hasClient()) { delay(1000); // We need to wait, until the client has connected } if (tcpClient && tcpClient.connected()) { tcpClient.stop(); } tcpClient = server.available(); } yield(); while(tcpClient.available()) { Serial.write(tcpClient.read()); } yield(); while(Serial.available()) { tcpClient.write(Serial.read()); } yield(); }
The sequence is quite simple:
Since the ESP8266 has only one CPU core, everything, including Wi-Fi, is handled by it. If the code takes too much CPU time in one step, the ESP8266 can crash. The "delay()" or "yield()" calls give some time to other components and prevent the ESP8266 from crashing.
The code can be uploaded to an ESP8266 (in my case, a NodeMCU V3) and connected to the Linux machine, which runs "pppd" (via the bash script from above). Ensure that the ESP8266 is connected as "ttyUSB0", or change the bash script to the correct USB port name.
(Connect the ESP8266 to the Linux machine first, then start the bash script.)
The IP address of the ESP8266 is needed, which should be found in the router where the ESP8266 is connected. In my case, it is "192.168.0.111".
The script for the D1 mini looks quite similar:
#include #include #include "SoftwareSerial.h" #include const char *ssid = "MySSID"; const char *pw = "MySecurePassword"; #define BAUDRATE 9600 #define TCP_PORT 8880 WiFiClient tcpClient; IPAddress master(192,168,0,111); // IP of the Main-Device SSD1306 display(0x3C, D2, D1); SoftwareSerial softSerial(D4, D3); // RX, TX void setup() { delay(500); display.init(); display.clear(); display.flipScreenVertically(); softSerial.begin(BAUDRATE); display.drawString(0, 0, "Starting Wifi"); display.display(); WiFi.mode(WIFI_STA); WiFi.begin(ssid, pw); while (WiFi.status() != WL_CONNECTED) { delay(500); } display.drawString(0, 15, "Setup OK"); display.display(); } void loop() { if(!tcpClient.connected()){ display.drawString(0, 30, "Looking for a Server"); display.display(); while (!tcpClient.connect(master, TCP_PORT)) { delay(100); } display.drawString(0, 45, "Server Connection OK"); display.display(); delay(2000); display.clear(); display.display(); display.drawString(0, 0, "Data transmission ongoing..."); display.display(); } yield(); while(tcpClient.available()) { int tb = tcpClient.read(); softSerial.write(tb); } yield(); while(softSerial.available()) { int sb = softSerial.read(); tcpClient.write(sb); } yield(); }
The sequence is very similar to the one for the ESP8266:
Since no flow control is used, the maximum bit rate is limited to 9600 bits/s. I have already added some wires to the CTS, RTS, and DTR pins of the m100 to improve this project. But currently, I have no time for this, and I'm happy that it is running at 9600 bits/s (around 1KB/s).
Here is the m100 in action with a wireless page load of http://light.palm2000.com:
(Video is without sound.)