UART to WiFi Bridge using Photon

Now, I know this can’t be all that difficult…I’m just really bad at looking stuff up.

Does anyone know where I can find some code to use the Photon as a simple UART to WiFi bridge? I gotta believe at least several people have done this already, but I’ve spent several hours looking, to no avail.

Any and all help and/or guidance would be very much appreciated.

Cheers,

Eugenio

I did a Serial to Electron Bridge for a home automation project… but the data crossing is minimal… it is not a device to piggyback 3G on top of a Ethernet or Wifi connected device.

2 Likes

@eugenio, I’ve been around since the Core and I don’t recall anyone doing this. There are a number of factors to consider, including:

  1. Is it plain UART or RS232 with full hardware handshaking?
  2. Is it streaming or message based?
  3. Are the two Photons with the same network or not?

It could be done a whole bunch of ways including UDP or TCP. You will need to consider how one Photon gets the other Photon’s IP. Yada, yada, yada.

Perhaps I should ask the simpler question. What is your application? :wink:

1 Like

Thanks for the reply, Bulldog! Fortunately, I don’t need to implement a cellular connection…at least not for the first go round. The plan is to simply implement a UART to WiFi bridge to connect another (rather dumb) embedded microcontroller device to a WiFi network, so that a PC on the same network can exchange fairly short messages with the device. One could think of it as using the Photon as a simple WiFi adapter, like the Lantronix WiPort, the GridConnect HF-A11 or about a couple dozen similar products.

I was able to find code to do this with an Espressif ESP8285, another WiFi enabled microcontroller with which you may be familiar. It even occurred to me to try to build that code for the Photon and see how many gazillion errors I got, but that sounded a bit too much like despairation

In any case, thanks much for the assistance.

Eugenio

Thanks for the git-back Peekay. It’s plain UART; RXD, TXD and GND, so no hardware handshaking. The interface is intended to be message based, with no streaming involved. And there’s only one Photon involved. Its UART will be connected to our (rather dumb) existing microcontroller based device, called an MDT. The Photon’s WiFi adapter will connect to our WiFi network, so that a PC on that same network can exchange fairly short messages with the MDT. As I mentioned to Bulldog, I’ve already found working code to do this with the Espressif ESP8285, which seems to work quite well. Does that pretty much cover it?

@eugenio, can you provide a link to the ESP code so I can see how easy it would be to port?

Most certainly! You can find it at this URL:

And thanks.

@eugenio, I believe this would be straight forward to port but without AP mode. I could take a crack at it if you can test it once ported. If I understand correctly:

PC <–> WiFi … Photon <–> MDT

The nice thing about the Photon is it can Particle.publish() its IP address so you don’t have to go hunting for it.

:slight_smile:

2 Likes

@eugenio, here is the port for you to test!

// Photon WiFi <-> UART Bridge
// by RoboRemo
// www.roboremo.com

// Disclaimer: Don't use RoboRemo for life support systems
// or any other situations where system failure may affect
// user or environmental safety.

#include "Particle.h"

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(SEMI_AUTOMATIC);


// config: ////////////////////////////////////////////////////////////
#define UART_BAUD 9600
#define packTimeout 5		// ms (if nothing more on UART, then send packet)
#define bufferSize 8192		// I suspect you can make this much smaller in your application

#define PROTOCOL_TCP
//#define PROTOCOL_UDP



// For STATION mode:
// Credentials already configured and stored in Photon
const int port = 9876;
// You must connect the phone to the same router,
// Then somehow find the IP that the Photon got from router, then:
// menu -> connect -> Internet(TCP) -> [IP]:9876
//////////////////////////////////////////////////////////////////////////


#ifdef PROTOCOL_TCP
TCPServer server = TCPServer(port);
TCPClient client;
#endif

#ifdef PROTOCOL_UDP
Udp udp;
IPAddress remoteIp;
#endif


uint8_t buf1[bufferSize], buf2[bufferSize];
uint8_t i1=0, i2=0;

char myIpString[24] = "";

void setup() {

	Serial.begin(UART_BAUD);	// USB port for debugging
	Serial1.begin(UART_BAUD);	// MDB is on Serial1 of Photon

	Particle.variable("endpoint", myIpString, STRING);

	// STATION mode (Photon connects to router and gets an IP)
	Particle.connect();	// Start WiFi connection
	if (!waitFor(Particle.connected, 30000)) {		// Wait 30 seconds for WiFi and Cloud to connect and if not connected, reset the Photon and restart!
		System.reset();								// This is quick and dirty and there is better code on many topics to handle WiFi connectivity
	}

	// WiFi and Cloud connected, publish local IP address and also set a Particle.variable() to access anytime
	IPAddress myIp = WiFi.localIP();
	sprintf(myIpString, "%d.%d.%d.%d:%d", myIp[0], myIp[1], myIp[2], myIp[3], port);
	Particle.publish("MDBip", myIpString, 60, PRIVATE);

#ifdef PROTOCOL_TCP
	Serial.println("Starting TCP Server");
	server.begin(); // start TCP server 
#endif

#ifdef PROTOCOL_UDP
	Serial.println("Starting UDP Server");
	udp.begin(port); // start UDP server 
#endif
}


void loop() {

#ifdef PROTOCOL_TCP
	if(!client.connected()) { // if client not connected
		client = server.available(); // wait for it to connect
		return;
	}

	// here we have a connected client
	if(client.available()) {
		while(client.available()) {
			buf1[i1] = (uint8_t)client.read(); // read char from client (RoboRemo app)
			if(i1<bufferSize-1) i1++;
		}
		// now send to MDB serial port:
		// Serial.write(buf1, i1);		// uncomment for debugging
		Serial1.write(buf1, i1);
		i1 = 0;
	}

	if(Serial1.available()) {
		// read the data until pause:
		while(1) {
			if(Serial1.available()) {
				buf2[i2] = (char)Serial1.read(); // read char from MDB serial port
				if(i2<bufferSize-1) i2++;
			} else {
				//delayMicroseconds(packTimeoutMicros);
				delay(packTimeout);
				if(!Serial1.available()) {
					break;
				}
			}
		}
		
		// now send to WiFi:
		//client.write((char*)buf2, i2);
		client.write((uint8_t*)buf2, i2);
		i2 = 0;
	}
#endif	// PROTOCOL_TCP



#ifdef PROTOCOL_UDP
	// if there’s data available, read a packet
	int packetSize = udp.parsePacket();
	if(packetSize>0) {
		remoteIp = udp.remoteIP(); // store the ip of the remote device
		udp.read(buf1, bufferSize);
		// now send to MDB serial port:
		Serial.write(buf1, packetSize);
		// Serial.write(buf1, packetSize);		// uncomment for debugging
	}

	if(Serial1.available()) {
		// read the data until pause:
		//Serial.println("sa");
		while(1) {
			if(Serial1.available()) {
				buf2[i2] = (char)Serial1.read(); // read char from UART
				if(i2<bufferSize-1) {
					i2++;
				}
			} else {
				//delayMicroseconds(packTimeoutMicros);
				//Serial.println("dl");
				delay(packTimeout);
				if(!Serial1.available()) {
					//Serial.println("bk");
					break;
				}
			}
		}

		// now send to WiFi:  
		udp.beginPacket(remoteIp, port); // remote IP and port
		udp.write(buf2, i2);
		udp.endPacket();
		i2 = 0;
	}
#endif	// PROTOCOL_UDP
}
4 Likes

Hello peekay,

Thanks much for the code. I should be able to take it for a spin today, and will let you know how it goes.

Much Obliged,

eugenio

2 Likes

Hello again, peekay,

I most sincerely appreciate the code, which appears to work perfectly. I do hope a time will come when I can return the favor.

Cheers,

eugenio

1 Like

So does this code allow 2 UART devices to communicate as normal over WiFi?

Sounds cool if so.

@RWB, the code allows a PC to connect to a serial device through a Photon using TCP or UDP. It is not setup the way you mentioned.

@eugenio, super glad it’s working! :wink:

1 Like

Would it be much more work to make this talk to another photon instead of a pc? I need to have 2 photons connect their serial ports together to over wifi.

@darkstar2002, it should be easy. However with no flow control, you need to make sure the Serial buffer (64 bytes) doesn’t overflow. You could use @rickkas7’s serial buffer code to help with that: