Skip to content

Week 4, Electronics Production

Objectives

Group assignment:

Demonstrate and compare the toolchains and development workflows for available embedded architectures

Document your work to the group work page and reflect on your individual page what you learned

Individual assignment:

Browse through the datasheet for your microcontroller

Write a program for a microcontroller, and simulate its operation, to interact (with local input &/or output devices) and communicate (with remote wired or wireless connection)

Group

In the group session I learned some different tool chains to program the XIAO boards and the nuances of them. Since the Aruduino IDE is robust and seemed easy to use with a number of libraries available, then I will likely that that forward. Circuit Python seemed to be a bit of a pain to get up and running having to load the firmware every time and as soon as an Arduino program was pushed to it, it needed to be reloaded.

Compare Tool Chains

Microcontroller Review

For the datasheet review I explored the XIAO ESP32C3. I chose this as I purchased a few for myself to play with and was interested in learning more. I am also considering using it or one of the other XIAO boards in my final project so it was good to get familiar with it.

Datasheet Review

The datasheet provided some key insights that will be helpful.

IO and Pin Assignments

The XIAO has 14 exposed pins and 11 are avaiable for IO with the other 3 being 3.3V, 5V, and ground. Three of them can be used for analog IO, any of hte 11 can be used for digital IO, and some of hte pins are available for communication protocols like IIC, UART, and SPI.

I addition to the exposed pins there are pads on the bottom of the board that can be used for a 3.7V LiPo battery.

The board is setup for 3.3V logic which will be important to know when connecting sensors.

Wireless

Since the XIAO has an ESP32C3 under the hood, it has both WiFi and BLE capability. The datasheet provides example usage for each of the wireless options.

WiFi

The C3 supports WiFi standard IEEE 802.11b/g/n which is compatible with most netoworks in the wild. Example code is provided for how to scan and connect to WiFi and how to use the XIAO as an access point. The code samples provided are all meant to work with the Arduino IDE. There is also documentation on how to use the device in the ESPHome and Home Assistant network.

BLE

The XIAO supports Bluetooth 5 (LE) connectivity which can be used with most modern BLE powered devices. The datasheet provides sample code for how to scan and read from other BLE devices, or to use the XIAO as a perifferal and broadcast its own data. There is also documentation about how to use it with the Lightblue BLE app to communicate with the device. I may be tempted to use this capability in my final project to communicate colors for the LEDs I want to use.

Programming Languages

The datasheet shows that the XIAO can be programmed with a number of different languages including Arudino IDE, Circuit Python, Micro Python, and Zephyr RTOS. I have the most experience with the Arduino IDE and libraries so I will likely use that for my programming work. However, I may explore Circuit Python too.

Simulation

I chose to simulate the XIAO ESP32C3 in Wokwi to get it to control addressable LEDs

Inputs: Momentary buttons

Outputs: Neopixel LED ring Discreet LEDs

Start

I started by testing out the sample project for the XIAO ESP32C3. The sample project had a simple program to cycle through blinking 3 LEDs. This allowed me to test the Wokwi interface in anticipation of a more complex sim.

Starting sample program

Neopixel Ring

Next I added a Neopixel ring to the workspace. It is a 5V power component, so I hooked up VCC to the 5V pin, GND to GND, and the data pin to pin 7 on the XIAO. The DOUT pin was left unconneted as I am not chaining them together. As this component requires a library to run, I had to also use the Wokwi command to insert the Adafruit Neopixel library. I then pulled a sample simple program example from the Neopixel library inside of the Arduino IDE and pushed it to the board to simulate the ring turning on one color.

Testing a simple Neopixel ring command in Wokwi

Adding Button to Change Color

Next I added a single button to control the amount of red for each pixel. I added a button and a resistor the workspace and connected the button to pin 10. I updated the code to read the button state and increment the brightness of the red output to the Neopixel by 10 each time it was pressed and to go to zero if the value is over 255 (the max for the LED). I also left the discreet LEDs in the code and had the red LED turn on when the button was pressed so that the user knows they are incrementing the red.

Adding buttons to the sim

One small problem I had was in the LED definition as defining the pins this way required the use of the GPIO number not the D number. So D2 was actually GPIO4.

Neopixel and Button Test
#include <Adafruit_NeoPixel.h>

//Neo Stuff
#define PIN 20 // Pin for pixels
#define NUMPIXELS 16 // Popular NeoPixel ring size
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 50 // Time (in milliseconds) to pause between pixels

#define REDLED 4
#define BUTRED 10
int statered = 0;
int butcount=0;
int r=50;  //red value

void setup() {
  Serial.begin(115200);

  pinMode(BUTRED, INPUT);

  pinMode(REDLED, OUTPUT);
  pinMode(D3, OUTPUT);
  pinMode(D4, OUTPUT);

  Serial.println("");
  Serial.println("Hello, XIAO ESP32-C3!");
  Serial.println("Welcome to Wokwi :-)");

  pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)

}

void loop() {

  pixels.clear(); // Set all pixel colors to 'off'

  statered = digitalRead(BUTRED);

 if (statered == HIGH) {
    // turn LED on:
    digitalWrite(REDLED, HIGH);
    delay(100);
    butcount=butcount+1;
    r=10+r;
    if (r>255){
      r=0;
    }
    Serial.print("Button count:");
    Serial.println(butcount);
    Serial.print("Red Value:");
    Serial.println(r);

  } else {
    // turn LED off:
    digitalWrite(REDLED, LOW);
  }

  for(int i=0; i<NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(r, 0, 0)); //set pixel color, obvy
    pixels.show();   // Send the updated pixel colors to the hardware.
    delay(DELAYVAL); // Pause before next pass through loop
  }
}

Adding the rest of the buttons

From there I added the other 2 buttons and copy and pasted the button read and increment code. I also added a serial print of the total RGB value to keep track of it as the buttons were being pushed.

Adding green and blue buttons to the sim

However, there was a mistake in this setup. When I pushed the green button, the red and green LEDs turned on and the RGB values incremented the same value. After looking at the circuit, I realized there was likely cross talk between the 3 buttons. So, I added 2 more resistors to sink the green and blue buttons seperately. I reran the code and this made it all work.

Adding green and blue buttons to the sim

Full Neopixel RGB with Buttons
//Program to simulate using buttons to change the color of an addressable LED ring
// Buttons increment the amount of each color to add to the ring

#include <Adafruit_NeoPixel.h>


//Neo Stuff
#define PIN 20 // Pin for pixels
#define NUMPIXELS 16 // Popular NeoPixel ring size
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 50 // Time (in milliseconds) to pause between pixels

//LED Pins (GPIO definition)

#define REDLED 4
#define GREENLED 5
#define BLUELED 6

//Button Pins
#define BUTRED 10
#define BUTGREEN 9
#define BUTBLUE 8

// State Variables
int statered = 0;  // variable for reading the pushbutton status
int stateblue = 0;
int stategreen =0;

int butcount=0;
int looper =0;  //looping variable for button

//turn the ring on a little bit
int r=50;  //red
int g=50; //green
int b=50; // blue


void setup() {
  Serial.begin(115200);
  pinMode(REDLED, OUTPUT);
  pinMode(GREENLED, OUTPUT);
  pinMode(BLUELED, OUTPUT);

  pinMode(BUTRED , INPUT);     // Button pin
  pinMode(BUTGREEN , INPUT);
  pinMode(BUTBLUE , INPUT);

  Serial.println("");
  Serial.println("Starting Sim");

  pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
}

void loop() {

  pixels.clear(); // Set all pixel colors to 'off'

  // read the state of the pushbutton value for each color
  statered = digitalRead(BUTRED);
  stategreen = digitalRead(BUTGREEN);
  stateblue = digitalRead(BUTBLUE);


// Red LED Check
  if (statered == HIGH) {
    // turn LED on:
    digitalWrite(REDLED, HIGH);
    butcount=butcount+1;
    r=10+r;
    if (r>255){
      r=0;
    }

    Serial.print("Red Value:");
    Serial.println(r);

  } else {
    // turn LED off:
    digitalWrite(REDLED, LOW);
  }

// Green LED Check
  if (stategreen == HIGH) {
    // turn LED on:
    digitalWrite(GREENLED, HIGH);
    butcount=butcount+1;
    g=10+g;
    if (g>255){
      g=0;
    }

    Serial.print("Green Value:");
    Serial.println(g);

  } else {
    // turn LED off:
    digitalWrite(GREENLED, LOW);
  }

// Blue LED Check
  if (stateblue == HIGH) {
    // turn LED on:
    digitalWrite(BLUELED, HIGH);
    butcount=butcount+1;
    b=10+b;
    if (b>255){
      b=0;
    }

    Serial.print("Blue Value:");
    Serial.println(b);

  } else {
    // turn LED off:
    digitalWrite(BLUELED, LOW);
  }


// Show the current RGB value
    Serial.print("RGB Value:");
    Serial.print(r);
    Serial.print(", ");
    Serial.print(g);
    Serial.print(", ");
    Serial.println(b);;

  for(int i=0; i<NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(r, g, b)); //set pixel color, obvy
    pixels.show();   // Send the updated pixel colors to the hardware.
    delay(DELAYVAL); // Pause before next pass through loop
  }


}

Wireless Simulation

I wanted to do a BLE sim, but Wokwi does not have this capability, so instead I added WiFi simulation. For this I setup the virtual XIAO to connect to its own virtual WiFi. Then I setup a sample app with Blynk to send commands to the board through the cloud and onto the virtual board through the virtual WiFi.

Wokwi and Blynk WiFi Sim

I started by reviewing this great video tutorial by techiesms that showed how to interact with Blynk and Wokwi. I then downloaded the Blynk library from the Arduino IDE and copied the code into the Wokwi browser using the same 3 LED starter template from Wokwi. I changed the WiFi to the Wokwi special WiFi credentials and started the sim.

I signed up for a Blynk account and got my credentials and account information and plugged those into the code. I then setup a new datastream in my Blynk account that I named "RedLed" and made it an integer type of data streamn connected to pin 5 of the XIAO board. In my app I added a toggle button to the UI and tied it the the "RedLed" data stream. I then ran the sim and was able to virtually toggle the LED on the screen on and off through my Blynk app. Since pin 5 was virtually connected to the green LED, that is the one that turned off and on.

Blynk simulation: toggling the Green LED on the virtual board through the app.

Blynk setup to control digital pin 5

Wokwi Blynk Sim

Simple Blynk Function
/*************************************************************
  Blynk is a platform with iOS and Android apps to control
  ESP32, Arduino, Raspberry Pi and the likes over the Internet.
  You can easily build mobile and web interfaces for any
  projects by simply dragging and dropping widgets.

    Downloads, docs, tutorials: https://www.blynk.io
    Sketch generator:           https://examples.blynk.cc
    Blynk community:            https://community.blynk.cc
    Follow us:                  https://www.fb.com/blynkapp
                                https://twitter.com/blynk_app

  Blynk library is licensed under MIT license
  This example code is in public domain.

 *************************************************************
  This example runs directly on ESP32 chip.

  NOTE: This requires ESP32 support package:
    https://github.com/espressif/arduino-esp32

  Please be sure to select the right ESP32 module
  in the Tools -> Board menu!

  Change WiFi ssid, pass, and Blynk auth token to run :)
  Feel free to apply it to any other example. It's simple!
 *************************************************************/

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial

/* Fill in information from Blynk Device Info here */
//I deleted my info
#define BLYNK_TEMPLATE_ID           "my ID"
#define BLYNK_TEMPLATE_NAME         "my Name"
#define BLYNK_AUTH_TOKEN            "my token"


#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Wokwi-GUEST";
char pass[] = "";

void setup()
{
  // Debug console
  Serial.begin(9600);

  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
}

void loop()
{
  Blynk.run();
}

Add Blynk App Functionality

#include <Adafruit_NeoPixel.h>    //neo


/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial

/* Fill in information from Blynk Device Info here */
//I deleted my info
#define BLYNK_TEMPLATE_ID           "my ID"
#define BLYNK_TEMPLATE_NAME         "my Name"
#define BLYNK_AUTH_TOKEN            "my token"


#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>


// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Wokwi-GUEST";
char pass[] = "";

//Neo Stuff
#define PIN 20 // Pin for pixels
#define NUMPIXELS 16 // Popular NeoPixel ring size
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 50 // Time (in milliseconds) to pause between pixels

// read rgb values and do the pixeling
BLYNK_WRITE(V4) {   
  // Called when virtual pin V2 is updated from the Blynk.App
  // V2 is a datastream of data type String assigned to a   
  // Blynk.App ZeRGBa widget.
  int r = param[0].asInt();
  int g = param[1].asInt();
  int b = param[2].asInt();
  Serial.print("V4: r = ");
  Serial.print(r);
  Serial.print("\t g=");
  Serial.print(g);
  Serial.print("\t b=");
  Serial.println(b);

  for(int i=0; i<NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(r, g, b)); //set pixel color, obvy
    pixels.show();   // Send the updated pixel colors to the hardware.
    delay(DELAYVAL); // Pause before next pass through loop
  }
}

void setup()
{
  // Debug console
  Serial.begin(9600);

  pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)

  delay(200); //just in case
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
}

void loop()
{
  Blynk.run();
}

BONUS: Simulation to Execution

As a test of the simulation, I pushed the Blynk Neopixel code to the XIAOESP32C3.

I started by placing the XIAO on a breadboard and wiring the LED to D3. Then I added an addressable LED strip and connected it to pin D7.

I copied the code from above and pasted it into the Arduino IDE and updated the WiFi credentials to those of the lab. Then I downloaded the Blynk and Adafruit Neopixel libraries. I uploaded the code and opened the Blynk app on my phone. Then I tested the buttons and the zebra color picker and watched the discreet LED turn on and off and the addressable LEDs change color.

Blynk demo running on code developed in Wokwi.