This page describes an experiment in using PyMata Express to communicate (using
[Firmata]) between a [Raspberry Pi] and an [Arduino] microcontroller.


!! Installing PyMata Express on Linux/Raspberry Pi

To install Pymata Express on Linux (including Raspberry Pi) and 
macOS computers, open a terminal window and type:
{{{
sudo pip3 install pymata-express
}}}


!! Installing Firmata Express on an Arduino

The [FirmataExpress|https://mryslab.github.io/pymata-express/firmata_express/] page
describes how to install it on an Arduino, using the Arduino IDE.

In a nutshell, this is not too difficult:

# [install the Arduino IDE|https://www.arduino.cc/en/main/software], and set your IDE to the type of Arduino you have from the {{Tools:Board}} menu
# using the {{Tools:Manage Libraries...}} command, install "FirmataExpress" and Erick Simoes' "Ultrasonic" libraries
# open up the {{File:Examples:FirmataExpress:FirmataExpress}} sketch, and use {{Sketch:Upload}} to upload the
FirmataExpress sketch to your Arduino

Then your Raspberry Pi can communicate with it using Python scripts, an example of which is shown below.
 

!! Example Code

Here is an example demonstrating using a callback to monitor
the state changes of a digital input pin.
{{{
import asyncio
import time
import sys
from pymata_express import pymata_express

"""
Setup a pin for digital input and monitor its changes
using a callback.
"""

# Setup a pin for analog input and monitor its changes
DIGITAL_PIN = 12  # arduino pin number
IDLE_TIME = .001  # number of seconds for idle loop to sleep

# Callback data indices
# Callback data indices
CB_PIN_MODE = 0
CB_PIN = 1
CB_VALUE = 2
CB_TIME = 3


async def the_callback(data):
    """
    A callback function to report data changes.
    This will print the pin number, its reported value and
    the date and time when the change occurred

    :param data: [[pin, current reported value, pin_mode, timestamp]
    """
    date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(data[[CB_TIME]))
    print(f'Pin: {data[[CB_PIN]} Value: {data[[CB_VALUE]} Time Stamp: {date}')


async def digital_in(my_board, pin):
    """
     This function establishes the pin as a
     digital input. Any changes on this pin will
     be reported through the call back function.

     :param my_board: a pymata_express instance
     :param pin: Arduino pin number
     """

    # set the pin mode
    await my_board.set_pin_mode_digital_input(pin, callback=the_callback)

    while True:
        try:
            await asyncio.sleep(IDLE_TIME)
        except KeyboardInterrupt:
            await board.shutdown()
            sys.exit(0)

# get the event loop
loop = asyncio.get_event_loop()

# instantiate pymata_express
board = pymata_express.PymataExpress()

try:
    # start the main function
    loop.run_until_complete(digital_in(board, 12))
except (KeyboardInterrupt, RuntimeError) as e:
    loop.run_until_complete(board.shutdown())
    sys.exit(0)
}}}

!! References

* [Introducing ItsyBitsy|https://learn.adafruit.com/introducing-adafruit-itsybitsy-m4] on Adafruit
* [ItsyBitsy M4 Pinout|https://learn.adafruit.com/introducing-adafruit-itsybitsy-m4/pinouts]
* [Arduino Uno/Nano/Mega as I2C Slave for an Raspberry Pi|https://forum.arduino.cc/index.php?topic=378528.0] (Arduino forum)

----

[{Tag RaspberryPi Arduino}]