Group assignment

For the group assignment, this week we have to compare as many tool options as possible. Below is a comparison of three different tools for creating applications that interface with microcontrollers: Flutter, MIT App Inventor, and Processing.

    Flutter:

    Description: Flutter is an open-source UI framework developed by Google. It allows you to build natively compiled applications for mobile, web, and desktop from a single codebase.

    Features:

    • Cross-Platform: Flutter supports multiple platforms, including Android, iOS, web, and desktop.
    • Rich Widgets: Flutter provides a wide range of customizable widgets for building beautiful UIs.
    • Hot Reload: Developers can see changes instantly during development.
    • Dart Language: Flutter uses the Dart programming language.
    • Use Case: Flutter is suitable for creating responsive and visually appealing GUIs for various devices, including microcontrollers.

    Pros and Cons:

    • Pros: Fast development, expressive UI, and strong community support.
    • Cons: May have a learning curve if you’re new to Dart and Flutter.

    MIT App Inventor:

    Description: MIT App Inventor is a visual development environment for creating Android apps. It’s beginner-friendly and uses a block-based programming approach.

    Features:

    • Visual Blocks: Drag-and-drop blocks to create app logic.
    • Live Testing: Test your app on a connected Android device or emulator.
    • Simple Interface: Ideal for beginners and educational purposes.
    • Use Case: Great for quickly prototyping simple apps and connecting them to microcontrollers.
    • Pros and Cons:

      • Pros: No coding experience required, rapid development.
      • Cons: Limited flexibility for complex apps.

    Processing:

    Description: Processing is an open-source programming language and environment for creative coding and visual arts.

    Features:

    • Graphics and Animation: Processing excels in creating visual content.
    • Java-Based: Uses a simplified version of Java.
    • Community Libraries: Extensive libraries for various tasks.

    Pros and Cons:

    • Use Case: Ideal for creating interactive visualizations and artistic GUIs.
    • Pros: Great for creative projects, strong community.
    • Cons: Not specifically designed for microcontroller interfaces.

Here is a link to the group assignment page.

Individual Assignments:

This week I decided to test out a few possibilities and options for the individual assignment. I wanted to understand how to use the bluetooth function on the nanoesp32 board, try out using MIT App Inventor and also test out the Processing software.

Bluetooth with nanoesp32

the arduino nano esp32 board, is really cool beccause as the name of this board suggests it is a combination of the arduino nano and the esp32. This board´s NORA- W106 moduel contains an esp32 chip, more specifically the esp 32 s3 and an onboard antenna. the esp 32 s3 has both wifi and bluetooth capabilities. but since for my project i plan on using blue tooht i ll focus on this feature. the esp32 supports Bluetooth 5 low energy (BLE). BLE is for short a power conserving variant of bluetooth. its primaraly used for short distance transmission of small amounts of data (low bandwidth). normal bluetooht is always on, but BLE is not. it is only on when a connection is initiated. this in turn means it consumes much less power than normal bluetooth

The esp 32 can act as a BLE server or a BLE client. and its easy to find BLe eamples for the esp32 in the esp 32 ble library in the arduino IDE environment. the code you write to use the bluethooth function should follow these steps:

  1. Create a BLE server (the esp32 acts as a server)
  2. Create a service (a service is a collection of characteristics)
  3. Create a characteristic on the service (a characteristic is a value that can be read or written)
  4. Create a descriptor on the characteristic (a descriptor is a value that describes the characteristic)
  5. Start the service
  6. Start advertising (this means the server is ready to accept connections and can be discovered by other devices)

the deconstruction of the code is as follows:

1. Include the BLE libraries

    
        #include <BLEDevice.h>
        #include <BLEUtils.h>
        #include <BLEServer.h>
    

2. Define a UUID for the Service and Characteristic.

    
        #define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
        #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
    

3. Setup() function

    
        Serial.begin(115200);
    

3.1. start the serial communication at 115200 baud rate.

    
        BLEDevice::init("BlueESP32");
        BLEServer *pServer = BLEDevice::createServer();
    

3.2. create the BLE device (I named it BlueESP32) and set it as the server

    
        BLEService *pService = pServer->createService(SERVICE_UUID);
    

3.3. create a service for the BLE server with the UUID defined earlier

    
        BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                     CHARACTERISTIC_UUID,
                                     BLECharacteristic::PROPERTY_READ |
                                     BLECharacteristic::PROPERTY_WRITE
                                     );
    

3.4. create a characteristic for the service, with the UUID defined earlier, and set the properties to read and write.

    
        pCharacteristic->setValue("Hello World");
    

3.5. This sets the characteristics value, in this case, the value is "Hello World"

    
        BLEAdvertising *pAdvertising = pServer->getAdvertising();
        pAdvertising->start();
    

3.6. Lastly start the service and start advertising

^^This code is the code you find when you open the BLE_server example in the arduino IDE. ( File > Examples > ESP32 BLE Arduino) here it is in its entirety:

        
            /*
                Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
                Ported to Arduino ESP32 by Evandro Copercini
                updates by chegewara
            */

            #include <BLEDevice.h>
            #include <BLEUtils.h>
            #include <BLEServer.h>

            // See the following for generating UUIDs:
            // https://www.uuidgenerator.net/

            #define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
            #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

            void setup() {
              Serial.begin(115200);
              Serial.println("Starting BLE work!");

              BLEDevice::init("Long name works now");
              BLEServer *pServer = BLEDevice::createServer();
              BLEService *pService = pServer->createService(SERVICE_UUID);
              BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                             CHARACTERISTIC_UUID,
                                             BLECharacteristic::PROPERTY_READ |
                                             BLECharacteristic::PROPERTY_WRITE
                                           );

              pCharacteristic->setValue("Hello World says Neil");
              pService->start();
              // BLEAdvertising *pAdvertising = pServer->getAdvertising();  // this still is working for backward compatibility
              BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
              pAdvertising->addServiceUUID(SERVICE_UUID);
              pAdvertising->setScanResponse(true);
              pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
              pAdvertising->setMinPreferred(0x12);
              BLEDevice::startAdvertising();
              Serial.println("Characteristic defined! Now you can read it in your phone!");
            }

            void loop() {
              // put your main code here, to run repeatedly:
              delay(2000);
            }
        
    

After understanding this, I followed another totorial, to turn on an off the onboard led of the nano esp 32 through bluetooth with my phone. in this totorial, by uploading this C++ code:

        
            // Turns an Arduino Nano ESP32 into a Bluetooth® Low Energy peripheral.
            // This BLE peripheral is providing a service that allows a BLE central 
            // to switch on and off the internal LED of the Arduino Nano ESP32.
            // https://tutoduino.fr/
            // Copyleft 2023
            #include <ArduinoBLE.h>
            BLEService ledService("19b10000-e8f2-537e-4f6c-d104768a1214"); // Bluetooth® Low Energy LED Service
            // Bluetooth® Low Energy LED Switch Characteristic - custom 128-bit UUID, read and writable by central
            BLEByteCharacteristic switchCharacteristic("19b10000-e8f2-537e-4f6c-d104768a1214", BLERead | BLEWrite);
            const int ledPin = LED_BUILTIN; // internal LED pin
            void setup() {
              Serial.begin(9600);
              // set LED pin to output mode
              pinMode(ledPin, OUTPUT);
              // BLE initialization
              if (!BLE.begin()) {
                Serial.println("starting Bluetooth® Low Energy module failed!");
                while (1);
              }
              // set advertised local name and service UUID:
              BLE.setLocalName("LED");
              BLE.setAdvertisedService(ledService);
              // add the characteristic to the service
              ledService.addCharacteristic(switchCharacteristic);
              // add service
              BLE.addService(ledService);
              // set the initial value for the characeristic:
              switchCharacteristic.writeValue(0);
              // start advertising
              BLE.advertise();
              Serial.println("BLE LED Peripheral");
            }
            void loop() {
              // wait for a Bluetooth® Low Energy central
              BLEDevice central = BLE.central();
              // check if a central is connected to this peripheral
              if (central) {
                Serial.print("Connected to central: ");
                // print the central's MAC address:
                Serial.println(central.address());
                // while the central is still connected to peripheral:
                while (central.connected()) {
                  // if the remote device wrote to the characteristic,
                  // use the value to control the LED:
                  if (switchCharacteristic.written()) {
                    if (switchCharacteristic.value()) {   // any value other than 0
                      Serial.println("LED on");
                      digitalWrite(ledPin, HIGH);         // will turn the LED on
                    } else {                              // a 0 value
                      Serial.println(F("LED off"));
                      digitalWrite(ledPin, LOW);          // will turn the LED off
                    }
                  }
                }
                // the central has disconnected
                Serial.println("Disconnected from central: ");
              }
            }
        
    

After uploading this code to the nano esp32, I downloaded the LightBlue application on my phone, and connected to the "LED" device. Then, by writing 1 or 0 in the characteristic, I was able to turn on and off the onboard LED of the nano esp32. Pretty cool! Although for the final project, I will not be sending data through hex ;P

Processing + arduino

processing is an open source software sketchbook that uses java as its programming language. and it works really well with arduino. in my case I will uplaod a program to my baord via arduino IDE and then use processing to create a GUI that will interact with the board (GUI = graphical user interface).

To start, I felt like a fish out of water, or to exagerate even more, I felt as if you asked a fish drowning in air, to write "an application that interfaces a user with an input &/or output device". obviously the fish would not know what to do at first. However we live in an age of information, and with a few searches on the internet I was able to find a few tutorials that helped me understand how to use processing with arduino (this made me feel like a fish that was given a glass of water to breathe in). if you are reading this, and also feel like a fish out of water, I recommend you check out these totorials: playlist for an intro to Processing and Control Arduino Using GUI (Arduino + Processing) and Connecting Arduino to Processing

Controlling an LED

Getting back on track, to start I followed the tutorial to control an LED. I used the board from electronics design week and uploaded the following code to the board:

Arduino code

        
            char val; // Data received from the serial port
            int ledPin = 3; // Set the pin to digital I/O 13
            boolean ledState = LOW; // To toggle our LED

            void setup()
            {
              pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
              // Initialize serial communications at a 9600 baud rate
              Serial.begin(9600);
              establishContact(); // Send a byte to establish contact until receiver responds
            }

            void loop()
            {
              if (Serial.available() > 0) { // If data is available to read,
                val = Serial.read(); // Read it and store it in val

                if (val == '1') // If we get a 1
                {
                  ledState = !ledState; // Flip the ledState
                  digitalWrite(ledPin, ledState);
                }
                delay(100);
              }
              else {
                Serial.println("Hello, I am processing it!"); // Send back a message
                delay(50);
              }
            }

            void establishContact() {
              while (Serial.available() <= 0) {
                Serial.println("A"); // Send a capital A
                delay(300);
              }
            }
        
    

upload the arduino code first, make sure to set the right LED pin

Processing code

        
            import processing.serial.*; //import the Serial library
            Serial myPort; //the Serial port object
            String val;
            // since we're doing serial handshaking,
            // we need to check if we've heard from the microcontroller
            boolean firstContact = false;

            void setup() {
              size(400, 400); //make our canvas 200 x 200 pixels big
              // initialize your serial port and set the baud rate to 9600
              String portName = "COM7"; //this setup is for windows port change the # to match your port
              myPort = new Serial(this, portName, 9600);
              myPort.bufferUntil('\n');
            }

            void draw() {
              //we can leave the draw method empty,
              //because all our programming happens in the serialEvent (see below)
            }

            void serialEvent( Serial myPort) {
              //put the incoming data into a String -
              //the '\n' is our end delimiter indicating the end of a complete packet
              val = myPort.readStringUntil('\n');
              //make sure our data isn't empty before continuing
              if (val != null) {
                //trim whitespace and formatting characters (like carriage return)
                val = trim(val);
                println(val);

                //look for our 'A' string to start the handshake
                //if it's there, clear the buffer, and send a request for data
                if (firstContact == false) {
                  if (val.equals("A")) {
                    myPort.clear();
                    firstContact = true;
                    myPort.write("A");
                    println("contact");
                  }
                }
                else { //if we've already established contact, keep getting and parsing data
                  println(val);

                  if (mousePressed == true)
                  { //if we clicked in the window
                    myPort.write('1'); //send a 1
                    println("1");
                  }

                  // when you've parsed the data you have, ask for more:
                  myPort.write("A");
                }
              }
            }
        
    

Run this code in processing, and by clicking with my mouse, I can turn the LED of my PCB on and off

Controlling a servo motor

Here I wanted to try out controlling a servo motor with processing. I used the same board from electronics design week, and plugged in my servo to the board. the arduino code for this is very simple:

    
        #include ESP32Servo.h
    

As always, when using servos, aways include the servo library, in my case because I´m using a nano ESP32, I found out in week 11 the servo.h library does not work with is board, so instead I used the ESP32Servo.h library.

    
        Servo myServo;
        int servoPosition = 0; // Initial position
    

Servo myServo; declares an instance of the Servo class named myServo. int servoPosition = 0; initializes an integer variable servoPosition with an initial value of 0.

    
        void setup() {
          myServo.attach(2); // Connect servo to pin 9
          Serial.begin(9600);
        }
    

In the void setup() function, myServo.attach(2); associates the servo motor with pin 2 on the Arduino board. Serial.begin(9600); initializes serial communication at a baud rate of 9600.

    
        void loop() {
          if (Serial.available() > 0) {
            int angle = Serial.parseInt(); // Read angle from Processing
            if (angle >= 0 && angle <= 180) {
              myServo.write(angle);
              delay(500); // Delay for servo movement
            }
          }
        }
    
    in the void loop() function
  • if (Serial.available() > 0) checks if there’s data available from the serial port (e.g., from a connected computer).
  • int angle = Serial.parseInt(); reads an integer value (angle) from the serial input.
  • if (angle >= 0 && angle <= 180) ensures that the angle value is within the valid range (0 to 180 degrees).
  • myServo.write(angle); sets the servo motor position based on the received angle.
  • delay(500); introduces a 500-millisecond delay to allow the servo to move smoothly.

here is the full code for arduino

        
            #include <Servo.h>

            Servo myServo;
            int servoPosition = 0; // Initial position

            void setup() {
              myServo.attach(2); // Connect servo to pin 9
              Serial.begin(9600);
            }

            void loop() {
              if (Serial.available() > 0) {
                int angle = Serial.parseInt(); // Read angle from Processing
                if (angle >= 0 && angle <= 180) {
                  myServo.write(angle);
                  delay(500); // Delay for servo movement
                }
              }
            }
        
    

upload this code to the board, and then run the following code in processing

Processing code

        
            import processing.serial.*;

            Serial arduinoPort; // Serial port for communication with Arduino
            boolean servoMoved = false; // Flag to track servo position
            Button servoButton; // Declare the button

            void setup() {
              size(400, 200);
              String[] portNames = Serial.list();
              if (portNames.length > 0) {
                arduinoPort = new Serial(this, portNames[0], 9600); // Change baud rate if needed
              } else {
                println("No Arduino port found. Make sure it's connected.");
                noLoop();
              }

              // Create the button
              servoButton = new Button(width / 2 - 50, height / 2 - 20, 100, 40, "Move Servo");
              servoButton.onClick(() -> {
                if (!servoMoved) {
                  arduinoPort.write("90"); // Send "90" to Arduino
                  servoMoved = true;
                } else {
                  arduinoPort.write("0"); // Send "0" to return servo to initial position
                  servoMoved = false;
                }
              });
            }

            void draw() {
              background(220);
              // Display the button
              servoButton.display();
            }

            class Button {
              float x, y, w, h;
              String label;
              Runnable onClickAction;

              Button(float x, float y, float w, float h, String label) {
                this.x = x;
                this.y = y;
                this.w = w;
                this.h = h;
                this.label = label;
              }

              void display() {
                // Button appearance
                fill(255);
                stroke(0);
                rect(x, y, w, h, 10); // Rounded corners
                fill(0);
                textAlign(CENTER, CENTER);
                textSize(16);
                text(label, x + w / 2, y + h / 2);
              }

              void onClick(Runnable action) {
                onClickAction = action;
              }

              void checkClick(float mx, float my) {
                if (mx > x && mx < x + w && my > y && my < y + h) {
                  onClickAction.run();
                }
              }
            }

            void mousePressed() {
              servoButton.checkClick(mouseX, mouseY);
            }
        
    

In summary, this code sets up a simple graphical interface with a button that interacts with an Arduino via a serial port. When the button is clicked in the Processing window, the Arduino receives a command to move the servo motor 90 degrees. Clicking the button again sends a command to return the servo to its initial position.