Introduction: Controlling ESP32 Running Micropython With Arduino Manager

This instructable is about Arduino Manager, a powerful general purpose iOS App which allows to control any Arduino (or Arduino compatible) board by the means of about 40 different Widgets.

Some of the available Widgets are:

  • Display Widget
  • LED Widget
  • Switch Widget Push Button Widget
  • Knob Widget
  • Slider Widget

Arduino Manager also provides (at an extra cost):

  • Code Generator: This add-on allows to generate the basic Arduino code for supporting the Widgets you have chosen.
  • PIN Code Generator: Linking widgets to Arduino PINs this add-on dramatically speeds up Arduino code development. In many cases you don't need to write a single line of code.
  • Voice Commands: Enables to control most of the Arduino Manager Widgets by the means of voice commands (English only).

Support for ESP32 programmed by the Arduino IDE has been available for many versions, since version 15.0.0 Arduino Manager can also work with ESP32 running MicroPython code.

Arduino Manager for iOS is available from the iTunes Store at $7.99. It is also available for Android and Mac OS X (please, note that not all the widgets are available on all the platforms).

More information, documentation, video tutorials, libraries and examples on Arduino Manager are available here: Arduino Manager site.

Step 1: Initial Setup

This section covers how to install MicroPython on ESP32 and the required development tools.

We assume that Python is already installed and configured on your development computer (you can download Python from here: https://www.python.org/downloads/).

The following steps have to be completed only the first time you setup the board with MicroPython.

To set everything up and running follow these steps:

  • Open a command prompt
  • Install rshell and esptools with:
pip install rshell

pip install esptool
  • Download the last MicroPythonfirmware for ESP32 from here https://micropython.org/download. (See section “Firmware for ESP32 boards”)
  • Install the required driver and locate the USB port where the ESP32 is connected to following the instruction provided here Establish Serial Connection
  • Install MicroPython firmware to the board with:
esptool.py --chip esp32 --port <port> erase_flash

esptool.py --chip esp32 --port <port> --baud 460800 write_flash -z 0x1000 <firmware file>
  • To connect to the board, use the rshell:
rshell -p <port>
  • Double check that you are signed in to iCloud
    • If not, go to Settings and tap "Sign in to your iPhone"
  • Start Arduino Manager on your iPhone or iPad
  • Open the left side menu
  • Copy the required python support code to your iCloud Drive tapping on "Python Support Code"
  • Go back to the command prompt and issue following command to copy the required software:
    • Windows
    • cp -r iCloudDrive/iCloud~boco~fabrizio~ArduinoManager/Python/Support/* /pyboard/
    • macOS
    • cp -r /Users/<your user>/Library/Mobile\ Documents/iCloud~boco~fabrizio~ArduinoManager/Documents/Python/Support/* /pyboard/
    • Linux Since iCloud is not directly accessible from Linux, you have to use your preferred browser and download the Python/Support folder from iCloud.com to a directory of your choice and then enter the following command
    • cp -r <your path>/* /pyboard/
  • Close rshell entering exit
  • Now you are ready to build the simple example circuit and control it with MicroPython and Arduino Manager

Step 2: Test Circuit

Now we are ready to build a simple test circuit. Refer to the electric diagram and to the breadboard picture to build it.

The board measures Temperature (LM 35) and voltage to the potentiometer and then sends them to the iOS device.

The iOS device sends commands to turn on and off LED 1 (yellow) and commands to move Servo.

LED 2 (Red) shows when the iOS device is connected to the board.

These are the connection fro the SD Card reader:

  • CLK/SCK to GPIO18
  • DO/MISO to GPIO19
  • DI/MOSI to GPIO23
  • CS to GPIO17

Step 3: Configure and Run the Example Code

  • Use a text editor to open the example code (example.py) directly from your iCloud drive in the folder:
Arduino Manager/Python/Support

If you are using Linux use your download directory instead

  • Change the following parameters accordingly with your network
    • YOUR NETWORK SID
    • YOUR NETWORK PASSWORD
    • BOARD IP
    • BOARD PORT
    • NETWORK MASK (usually is 255.255.255.0)
    • GATEWAY ADDRESS
  • Connect the ESP32 board to your computer and launch the shell
rshell -p <port><port></port>
  • Copy the modified example to the board
    • Windows
    • cp -r iCloudDrive/iCloud~boco~fabrizio~ArduinoManager/Python/Support/example.py /pyboard/
    • macOS
    • cp -r /Users/<your user>/Library/Mobile\ Documents/iCloud~boco~fabrizio~ArduinoManager/Documents/Python/Support/example.py /pyboard/
    • Linux
cp -r <Your PATH>/example.py /pyboard/
  • Switch to Repl to issue commands to the board entering
repl
  • Start the example code with
import example

example.main()
  • You something like
INFO:AM Server:Server Init completed
INFO:AM Server:>>> Check Alarms <<< 
INFO:AM Server:socket_server ready on 192.168.1.233 port 80

shows up, you are good to go

  • Note 1: Every time you switch on the board, you have to connect to it using rshell, switch to repl and than start the example code. To automatically start the example code at power up, you have to rename the file example.py to main.py with
rshell -p <port>
cp /pyboard/example.py /pyboard/main.py
rm /pyboard/example.py

Step 4: Connect Arduino Manager to the ESP 32 Board

To connect Arduino Manager to the ESP32 board, follow these steps:

  • Start Arduino Manager on your iPhone / iPad
  • Open the left side menu
  • Tap on "Connections" to access the connections to the boards
  • Tap on "Add" to add a new connection
  • Enter the following information:
    • Connection Name: whatever you like. For example ESP32 running Python
    • IP Address: the same IP value you entered in the example.py
    • IP Port: the same value you entered in the example.py
    • Timeout: you can left it unchanged
  • Tap on "Ok"
  • Select the just created connection

A Few seconds later the connection indicator on the bottom left side of the screen should turn green and the red LED should torn on.

Step 5: Configure Arduino Manager

  • Switch to Edit using the bottom right switch
  • Tap somewhere and insert a Display Widget
  • Tap on field just down the display and enter: T
    • You should be able to read the temperature measured by LM 35
  • Add another Display Widget and enter: Msg
  • Double Tap on the Display Widget, tap Configure and switch to Text Only
    • A text message should roll over and over in the Display Widget
  • Add a Switch Widget and enter: S1
    • Tapping on the switch, you should be able to turn the yellow LED on and off
  • Add a LED Widget and enter: Led13
    • The LED should follow the yellow LED on the board
    • Double tapping on the LED Widget you can choose the preferred color
  • Add a Knob Widget and enter: Knob1
    • Moving the dial, the servo motor should change its position
  • Add an SD Widget
    • Double tapping on it you should be able to see the list of files in the root directory of the SD Card (if any) and open the files
  • Add a Push Button Widget and enter: Push1
    • Pressing the button, the red LED should turn off for a few milliseconds and then turn back on
    • Double tapping on the Push Button you can choose the preferred color
  • Add a Graph Widget and enter: Pot
    • Turning the potentiometer on the breadboard a graph should show up
  • Add a Timer Widget and enter: A1
    • Double tap the Timer Widget and set the time in a couple of minutes from the current time
    • When the timer expires, the servo motor is moved to its initial position and the connection LED flashes for a few milliseconds
  • Add a Logged Data Graph Widget and enter: TodayT
    • Double Tap the Widget and the tap Refresh
    • The graph shows the temperature values automatically stored into the SD card
  • Add a Command Widget and enter: Cmd_01
    • Double tap the Widget and enter: blink.
    • Double tap the Widget again.
    • Tap the button of Cmd_01, the red LED should turn off for a few milliseconds and then turn back on
  • Add a Console Widget
    • Every time you press the Cmd_01 button, a message should show up on the Console Widget

Note 1 - Move a Widget: To move a Widget:

  • Switch to edit mode
  • Long tap on the widget to move until the border gets red
  • Move the widget in the desired position

Note 2 - Delete a Widget: To delete a Widget:

  • Switch to edit mode
  • Long tap on the widget to move until the border gets red
  • Release your finger
  • Swipe down the widget

We have briefly explored some of the features of Arduino Manager and some of the available Widgets. There is much more to see and learn.

The next section is dedicated to learn more about the example python code.

Step 6: Understanding the Python Code

The python code for supporting Arduino Manager is mainly based on some callback functions:

  • doWork - This function is periodically called, and here goes your code to read sensors, command actuators and so on
  • processIncomingMessages - This function is called when data is received from the iOS device
  • processOutgoingMessages - Called periodically to send data to the iOS device
  • doSync - This function is called immediately after the iOS device is connected and is used to send status information to it
  • processAlarm - Called when an alarm is fired
  • deviceConnected - Called when the iOS device gets connected to the ESP32 board
  • deviceDisconnected - Called when the iOS device gets disconnected from the ESP32 board

Let's see each function.

In the doWork function the position of the potentiometer is read (pa35.read()) reading the value of the analog to digital converter connected to the analog pin 32. In the same way, the temperature sensor is read and the conversion from voltage to temperature is performed. After that the temperature is saved into in a log file (iosController.sdLog).

async def doWork():    
    global pot
    global temperature
    global todayTSamplingCounter
    global todayTNumberOfSamples
    
    pot = pa35.read()    
    temperature = 100 * getVoltage(pa32)
    
    if todayTSamplingCounter >= 10:
      todayTSamplingCounter = 0
      todayTNumberOfSamples += 1
      if iosController.sdFileSize('TodayT') == 0 or todayTNumberOfSamples == 100:
        iosController.sdPurgeLogData('TodayT')
        iosController.sdLogLabels('TodayT', 'V1')
        todayTNumberOfSamples = 0
      iosController.sdLog('TodayT', temperature)
    return

The processIncomingMessages is called for each message received and has two parameters:

  • variable - the name of the widget which is sending data
  • value - data associated to the widget.
async def processIncomingMessages(variable, value):
    global servoPos    
    if variable == 'S1':
      p5.value(int(value))
    if variable == 'Knob1':
      print('Knob1 %d' % int(value))
      servoPos = map(int(value), 0, 1023, 40, 115);
      servo.duty(int(servoPos))
    if variable == 'Push1'  and int(value) == 1: # only when the button is pushed
      await iosController.temporaryDigitalWrite(p16, 0, 500)
    if variable == 'Cmd_01':
      await iosController.consoleLog("Command: ")
      await iosController.consoleLogLn(value)
      if value == 'blink':
        await iosController.temporaryDigitalWrite(p16, 0, 200)
    return

When the S1 Switch Widget S1 sends "1", the p5 pin is set to 1 [p5.value(int(value))] and the LED connected to it turns on. When the Knob Widget Knob1 sends a value (in the range 0,1023), this value is converted in the range 40, 115 to control the servo motor [servo.duty(int(servoPos))]

The processOutgoingMessages is called periodically to send data to the connected iOS device.

async def processOutgoingMessages():
    await iosController.writeMessage('Pot',pot)
    await iosController.writeMessage('T',temperature)
    await iosController.writeMessage('Led13',p5.value())    
    return

The doSync function is called only once when the iOS device gets connected to the ESP32 board and sends information for initializing some Widgets like Switch Widget and Knob Widget and the Display Widget configured as Text Only.

async def doSync(variable):
    if variable == 'S1':
      await iosController.writeMessage(variable,p5.value())
    if variable == 'Knob1':
      await iosController.writeMessage(variable, map(servo.duty(), 40, 115, 0, 1023))
    if variable == 'Msg':
      await iosController.writeTxtMessage(variable,"Hello, I'm your ESP32 board running micropython")
    return