I see this one come up fairly often and I want to show how to connect the two but I always have too much other code around it. I wanted to try something super minimal.
The intent is to send an analog read to python and display it on the screen to demonstrate Arduino to Python, and send on and off times for the blinking from Python to Arduino.
So here's the Arduino side. It's going to run blink without delay with different on and off times and set up a WiFi server to listen to a socket from the python script. The client code is a version of @Robin2's code with the Serial swapped out for a WiFi client.
It will receive packets with < and > end markers. The first letter determines the intent and the rest is data. H sets the HIGH period and L sets the LOW period for the blink. So H50 set's the HIGH period to 50ms.
Also every 1 second it sends an analogRead from pin A0 back to the python code.
#include "WiFiS3.h"
#include "arduino_secrets.h"
const int ledPin = 13;
/// Blink variables
unsigned long lastMillis = 0;
unsigned long onTime = 500;
unsigned long offTime = 500;
// @Robin2 Receive with start and end markers variables
const byte numChars = 32;
char receivedChars[numChars];
// Variables for the WiFi Access Point
// char ssid[] = "WiFi_Test_AP";
// char pass[] = "";
WiFiServer server(2080);
IPAddress ipAddress(192, 168, 1, 77);
WiFiClient client;
void setup() {
Serial.begin(115200);
while (!Serial)
;
Serial.println("\n\n *** " __FILE__ " ***\n\n");
pinMode(ledPin, OUTPUT);
startWifi();
// Start the server
server.begin();
printWiFiStatus();
}
void loop() {
blink();
recvWithStartEndMarkers();
}
void blink() {
static unsigned long last = millis();
unsigned long now = millis();
static bool ledOn = false;
if (now - last >= (ledOn ? onTime : offTime)) {
last = now;
ledOn = !ledOn;
digitalWrite(ledPin, (ledOn ? HIGH : LOW));
}
}
// @Robin2 see: https://forum.arduino.cc/t/serial-input-basics-updated/382007
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
static unsigned long lastSend = millis();
if (client && client.connected()) {
while (client.available() > 0) {
rc = client.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
} else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
processReceivedChars();
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
if(client.connected() && (millis() - lastSend >= 1000)) {
lastSend = millis();
int ana = analogRead(A0);
client.print("<A");
client.print(ana);
client.print(">");
Serial.println(ana);
}
}
else {
client = server.available();
}
}
void processReceivedChars() {
// print the command to be sure what we got
Serial.print("New Command : ");
Serial.println(receivedChars);
unsigned long newVal = 0;
// The first character is the command and the new value starts after that.
switch (receivedChars[0]) {
case 'H': // Set the HIGH - ON time
// strtoul converts ascii text to an unsigned long
newVal = strtoul(receivedChars + 1, NULL, DEC);
onTime = newVal;
break;
case 'L': // Set the LOW - OFF time
newVal = strtoul(receivedChars + 1, NULL, DEC);
offTime = newVal;
break;
default:
Serial.println("Unknown Command");
}
}
// From AP_SimpleWebServer example in Arduino IDE (setup function)
void startWifi() {
// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true)
;
}
// check module firmware version
if (WiFi.firmwareVersion() < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}
WiFi.config(ipAddress);
int status = WL_IDLE_STATUS;
// attempt to connect to WiFi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to Network named: ");
Serial.println(ssid); // print the network name (SSID);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
}
// From AP_SimpleWebServer example in Arduino IDE
void printWiFiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
}
The Python side is all console. It's going to receive the data and every 100ms clear the console screen and print a 2 line UI. I've also got a TK version I'll post in a few.
To make input you Control-C to get a keyboard interrupt and that will pause the display and let you make input.
import socket, time
import threading, queue
from os import system
def main():
### Create the socket and connect
socketArgs = ('192.168.1.77', 2080)
arduino_socket = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
arduino_socket.connect(socketArgs)
### A queue to hold data from the socket
sock_queue = queue.Queue()
### define a function to read from the socket
def readFromSocket():
while True:
c = arduino_socket.recv(1)
sock_queue.put(c)
### Create a thread to run the above function and start it.
sock_thread = threading.Thread(target=readFromSocket, args=(), daemon=True)
sock_thread.start()
input_string = ""
parsing = False
analog_read = ""
### This will be the main program loop
while (True):
### The try will let us catch a keyboard interrupt (Ctrl-C)
### to stop the screen from clearing so you can input
try:
### Read characters from the queue and process
### ala @Robin2
while(sock_queue.qsize() > 0):
c = sock_queue.get().decode("utf-8")
if(c == '<'):
parsing = True
input_string = ""
elif(c == '>'):
parsing = False
if input_string[0] == 'A':
analog_read = input_string[1:]
elif parsing:
input_string += c
### Pause for 100ms so the screen doesnt flicker
time.sleep(0.100)
### Clear the console window
system('clear')
### Print the UI
print("Easy Console App\n\n")
print(analog_read)
### Catch the keyboard interrupt and take input
except KeyboardInterrupt:
### Add the start and end markers to the input
output_string = '<' + input("???") + '>'
### Send the input to the arduino
arduino_socket.send(output_string.encode("utf-8"))
if (__name__ == '__main__'):
main()
It's about as bare bones as it gets.