In this guide, we'll explore how to use the CodeCell to measure its rotation directly by reading the roll, pitch, and yaw angles. Understanding these angles is crucial in applications like robotics, drones, and motion tracking, where precise orientation data is needed.
CodeCell is equipped with a BNO085 motion sensor, which fuses data from an accelerometer, gyroscope, and magnetometer to compute rotation vectors. These vectors help determine the device's orientation in space in terms of roll, pitch, and yaw:
By continuously monitoring these values, CodeCell provides real-time orientation feedback, making it useful for a variety of motion-based applications.
To read the rotation angles, follow this simple example. This code initializes CodeCell's motion sensor and continuously prints the roll, pitch, and yaw values to the serial monitor.
#include <CodeCell.h>
CodeCell myCodeCell;
float Roll = 0.0;
float Pitch = 0.0;
float Yaw = 0.0;
void setup() {
Serial.begin(115200); // Set Serial baud rate to 115200. Ensure Tools/USB_CDC_On_Boot is enabled if using Serial.
myCodeCell.Init(MOTION_ROTATION); // Initializes Rotation Sensing
}
void loop() {
if (myCodeCell.Run(10)) { // Run every 10Hz
myCodeCell.Motion_RotationRead(Roll, Pitch, Yaw);
Serial.printf("Roll: %.2f°, Pitch: %.2f°, Yaw: %.2f°\n", Roll, Pitch, Yaw);
}
}
Explanation of the Code:
Initialize the CodeCell motion sensor to read rotation values.
Run the sensor at 10Hz (every 100ms) to get fresh data.
Print the roll, pitch, and yaw angles in degrees to the serial monitor.
This provides an accurate way to measure the orientation of CodeCell in real time.
One practical application of reading roll, pitch, and yaw is controlling a servo motor based on CodeCell's orientation. The following example maps the pitch angle to the servo’s position.
#include <CodeCell.h>
#include <ESP32Servo.h>
CodeCell myCodeCell;
Servo myservo;
float Roll = 0.0;
float Pitch = 0.0;
float Yaw = 0.0;
int servo_angle = 0;
void setup() {
Serial.begin(115200); // Set Serial baud rate to 115200
myCodeCell.Init(MOTION_ROTATION); // Initializes rotation sensing
myservo.attach(1); // Attaches the servo on pin 1 to the servo object
}
void loop() {
if (myCodeCell.Run(10)) {
// Read rotation angles from the BNO085 sensor
myCodeCell.Motion_RotationRead(Roll, Pitch, Yaw);
// Convert the pitch angle to a servo angle
servo_angle = abs((int)Pitch);
servo_angle = (180 - servo_angle);
// Limit the servo angle to the range 0-60 degrees
if (servo_angle > 60) {
servo_angle = 60;
} else if (servo_angle < 0) {
servo_angle = 0;
}
Serial.println(servo_angle); // Print the servo angle for debugging
myservo.write(servo_angle); // Set the servo position
}
}
Explanation:
Maps the pitch angle to control the servo position.
Limits the servo angle to a safe range (0-60 degrees) to avoid excessive motion.
Uses 10Hz updates to keep the response smooth.
By directly reading roll, pitch, and yaw, you can unlock advanced motion-based applications with CodeCell. Try modifying the examples and integrating them into your own projects. Check out the CodeCell GitHub Repository for more examples and technical documentation!
The CodeCell offers flexibility in power supply options, allowing it to be powered through either the LiPo battery connector, a USB-C cable, or both simultaneously. This ensures adaptability across different use cases.
Power management is handled by the BQ24232 battery management chip, which supports Dynamic Power-Path Management (DPPM). This allows the CodeCell to run from external power while simultaneously charging the battery. The battery charging process follows three key phases:
The BQ24232 chip regulates the output voltage, supporting a maximum output of 1500mA when powered by the LiPo battery and 450mA when powered via USB.
By default, the LiPo battery charge current is set to 90mA. This is optimized for the optional 170mAh LiPo battery, ensuring a safe and balanced charging rate.
Advanced users who wish to modify the charge current can do so by replacing 0402 resistor R12. However, this modification requires precise soldering skills, as 0402 components are extremely small. For further details, refer to the BQ24232 datasheet.
The CodeCell library provides visual feedback on charging and power status using the onboard RGB LED:
By default, the CodeCell enters Sleep Mode while charging to maximize efficiency. However, starting from software release v1.2.7, users can override this behavior using the USBChargeState() function, which keeps the CodeCell awake during charging.
To keep the CodeCell awake while charging, add the following code to your setup function:
void setup() {
Serial.begin(115200); // Set Serial baud rate to 115200
// Ensure Tools/USB_CDC_On_Boot is enabled if using Serial
myCodeCell.Init(LIGHT); // Initializes Light Sensor
myCodeCell.USBChargeState(1); // Keeps CodeCell awake during charging
}
Behavior with USBChargeState(1):
This feature is useful for applications that require CodeCell to remain active while charging, such as continuous data logging or IoT monitoring.
With this information, you now have a full understanding of how CodeCell’s charging system works, including its default behaviors and customization options!
CodeCell is a compact module featuring the ESP32-C3, multiple power options, and integrated sensors, all within a tiny 1.85 cm wide form factor. These features make it a powerful tool for a wide range of applications.
In this first section, we'll start by getting familiar with the circuitry that forms the CodeCell. After that, we'll walk through the simple steps to set up your CodeCell.
To follow the circuitry in more detail, check out the CodeCell schematics here.
At the heart of the CodeCell is the ESP32-C3 module, a compact microcontroller known for being maker-friendly in the IoT space. It combines an Arduino-compatible architecture with built-in Wi-Fi and Bluetooth Low Energy (BLE) capabilities.
The ESP32-C3 module's PCB antenna is positioned on one side, away from other components, to minimize interference and improve signal transmission and reception. This placement helps reduce the impact of ground planes or other conductive surfaces that could degrade antenna performance. Testing has shown that the antenna’s performance remains unaffected in battery powered-applications, with minimal interference when plugging in the USB-C cable for charging, as these cables are typically shielded.
The ESP32-C3 provides 4 MB of Flash and 400 KB of SRAM, making it capable of running most applications. Its 32-bit RISC-V single-core processor, running at up to 160 MHz, efficiently handles various tasks. The ESP32-C3 also includes a USB Serial/JTAG Controller, allowing CodeCell to be reflashable through the USB-C port and facilitating serial communication and debugging.
The CodeCell offers flexibility in power supply options. It can be powered through the LiPo battery connector, a USB-C cable, or both.
Power management is handled by the BQ24232 battery management chip, which supports Dynamic Power-Path Management (DPPM). This allows CodeCell to be powered while simultaneously charging the battery. The battery charging process follows three phases:
The output voltage is regulated through the BQ24232 chip, supporting up to 1500mA when powered by the LiPo battery and 450mA via USB.
By default, the LiPo battery charge current is set to 90mA to ensure a safe charge rate for the optional 170mAh LiPo battery. Advanced users can adjust this rate by replacing 0402 resistor R12, following the formula R = 870/Ichrg. This modification is recommended only for those skilled in soldering 0402 components. See the BQ24232 datasheet for details.
The CodeCell library provides visual feedback on power status through the onboard addressable RGB LED:
The board also includes 100µF bulk capacitors for stable power delivery and TVS diodes for ESD protection. A 3.3V Low Dropout (LDO) regulator (NCP177) provides a steady 500mA output with a 200mV dropout at max current.
The compact design of the CodeCell required careful placement of GPIO and power pins. The board is divided into functional sections:
The CodeCell is equipped with onboard sensors to enhance its functionality:
VCNL4040 Light Sensor:
Optional 9-axis BNO085 Motion Sensor:
Our CodeCell library simplifies sensor configuration and reading each sensor.
Many ESP32 development boards include RST (Reset) and BOOT buttons. However, the ESP32-C3 on CodeCell can enter boot mode automatically via the Arduino IDE, eliminating the need for these buttons and allowing for a smaller form factor.
If the CodeCell encounters an exception (causing continuous resets), it can be manually forced into boot mode for reflashing:
Following these steps will bring the CodeCell back to life.
Each CodeCell package includes:
If you’ve just got your hands on the CodeCell, you're in for a treat. This tiny module is designed to simplify your DIY projects with multiple features packed into a penny-sized board. In this guide, we’ll walk you through:
CodeCell is a compact and versatile module featuring the ESP32-C3, multiple power options, and integrated sensors, all within a tiny 1.85 cm wide form factor. These features make it a powerful tool for a wide range of applications.
In this first section, we'll start by getting familiar with the circuitry that forms the CodeCell. After that, we'll walk through the simple steps to set up your CodeCell.
ESP32C3 Module
At the heart of the CodeCell is the ESP32C3 module, a compact microcontroller known for being maker-friendly in the IoT space. It combines an Arduino-compatible architecture with built-in Wi-Fi and Bluetooth Low Energy (BLE) capabilities. This integration offers the most popular connectivity options while maintaining a small form factor.
The ESP32C3 module's PCB antenna is positioned on one side, away from other components, to minimize interference and improve signal transmission and reception. This placement helps reduce the impact of ground planes or other conductive surfaces that could degrade antenna performance. The components on the bottom side are kept within the recommended clearance for the antenna. From testing we found that the antenna's performance remains unaffected by the minimal interference from a USB-C cable, as these cables are typically shielded.
The ESP32-C3 provides plenty of memory, with 4 MB of Flash and 400 KB of SRAM, making it capable of running most typical applications. Its 32-bit RISC-V single-core processor, running at up to 160 MHz, efficiently handles various tasks. This combination of memory and processing power makes the ESP32-C3 suitable for a wide range of uses.
The ESP32C3 module also supports a USB Serial/JTAG Controller, allowing us to make the CodeCell reflashable through the USB-C port and to send serial data for communication and debugging.
Power Management
The CodeCell offers flexibility in power supply options. It can be powered through the LiPo battery connector, a USB-C cable, or both.
The LiPo battery connector makes it easier than ever to safely connect the battery without the need for soldering or risking accidental shorting it.
The USB-C port serves dual purposes: it is used for both powering the device and/or reprogramming it. This multi-power option is enabled through the BQ24232 battery management chip, which features dynamic power-path management (DPPM) that can power the system while simultaneously and independently charging the battery. The battery charging process is managed in three phases: conditioning precharge, constant current, and constant voltage. To protect the battery the output voltage (Vo) is regulated though the BQ24232 chip. This output supports a maximum output current of 1500mA when powered by the LiPo battery and 450mA when powered via USB.
By default, the LiPo battery charge current is set to 90mA, ensuring a balanced and a safe charge rate for the optional 170mAh LiPo battery. Further more, for those who wish to adjust the charging rate, 0402 resistor R12 have to be de-soldered and replace it with a new resistor based on the formula (R = 870/Ichrg). This is only recommended for soldering pros, who aren’t afraid of wrestling with tiny 0402 components! Check the BQ24232 datasheet for more information on the battery charging.
The CodeCell library can provides visual feedback on the battery/usb power status via the onboard addressable RGB LED:
The power regulation is further supported by multiple decoupling capacitors, including up to two bulk capacitors of 100µF each, placed next to the battery-connector. These capacitors are connected to the 3.3V and the output Vo pins to ensure stable power delivery. Additionally, the board features two TVS diodes for protection; one safeguards the USB input 5V voltage (Vin), and the other protects the output voltage (Vo). These TVS diodes provide protection against electrostatic discharges (ESD), capable of safely absorbing repetitive ESD strikes above the maximum level specified in the IEC 61000-4-2 international standard without performance degradation.
The board also includes an onboard 3.3V Low Dropout (LDO) regulator, which provides a stable power supply to its low-voltage components. This tiny NCP177 LDO chip can output up to 500mA output current with a typically low dropout voltage of 200mV at 500mA.
GPIO and Power Pins
Given the compact design, the main challenge was to maximize the use of GPIO pins. We tackled this by dividing each of the three available sides of the CodeCell into different I/O sections based on their applications. We also placed power pins along the edges of the module for easy connection to various power sources, allowing you to connect other modules, sensors, and actuators to different sides.
On the bottom side, 3 out of 5 pins are used for power: a ground pin (GD), a 3.3V logic-level power pin (3V3) and a 5V input charge pin (5V0). This 5V0 pin is connected to the USB input-voltage. This means you can use it to get 5V power when the USB is connected, or you can use it as a power input for charging instead of using the USB.. The other 2 pins are the I2C SDA & SCL pins for adding external digital sensors. If your not using any external and the light/motion sensors, these I2C pins can be set up as GPIOs.
The other two sides each have a ground pin (GD) and a voltage output pin (VO). Each side also features 3 programmable GPIO pins (IO1, IO2, IO3, IO5, IO6, IO7), which can all be configured as PWM pins (ideal for directly connecting an h-bridge for actuator/motor control). IO1, IO2, and IO3 can also be used as ADC pins.
Sensing Capabilities
The CodeCell's standout features include its onboard sensors. Each unit comes equipped with a built-in light sensor, and there's also an optional motion sensor available to elevate your project's motion detection—especially useful for robotics and wearables!
Next we'll dive into how the CodeCell library simplifies both configuring these sensors and reading their data.
What about the BOOT Pin?
Some ESP32 development boards include both a RST (Reset) button and a BOOT button to manually put the device into programming mode. However, the ESP32-C3, such as the one on the CodeCell module, can automatically enter boot mode through the serial interface when using the Arduino IDE. This means the CodeCell doesn't need dedicated RST or BOOT buttons, which allowed us to make it as small as it is.
In the rare case that your CodeCell freezes or encounters an exception (causing it to continuously reset), you can manually force it into boot mode to reflash the firmware. To do this, simply follow these steps:
Following these steps will restore your CodeCell back to life.
To make programming even easier, the CodeCell library provides a wide array of functions for initializing, reading, and managing sensors and power. In this section we're going to explain everything you need to know about setup up your device and it's library.
Unboxing Your CodeCell
Let’s start with what you’ll find inside the box. Depending on the options you selected during checkout, in the box you'll find:
Powering Up Your CodeCell for the First Time
Let's start by plugging in a USB-C cable! Once your CodeCell receives power it should:
Setting Up Your CodeCell
Next step is to connect the CodeCell to Arduino IDE and run a sketch:
With your IDE all set up, we can now go ahead an install the "CodeCell" library. To do this go to 'Sketch>Include Library>Manage Libraries' - the 'Library Manager' should open up. Just type "CodeCell" and click 'Install' to download the latest version of the CodeCell.
We are continuously updating and adding new features to this library, so make sure you're using the latest version.
To quickly get familiar with this library, go to 'File > Examples > CodeCell,' where you'll find multiple examples you can use and modify for your projects. We recommend starting with the 'GettingStarted' example, which contains just a few lines of code but explains all the sensing functionalities available with CodeCell.
Once you select an example sketch, click the 'Upload' button to flash the code onto your CodeCell. After uploading, open the Serial Monitor 'Tools > Serial Monitor' to see serial data from your CodeCell.
Here are some additional CodeCell tutorials to help you get started with various applications:
CodeCell Library Functions
To explore the code further, let's break down all the functions and explain what each one does:
Initializing CodeCell
The first step in using the CodeCell is to initialize it. This is done using the `myCodeCell.Init()` function, which allows you to specify the sensors you want to enable.
Available Sensing Macros:
You can combine multiple macros using the `+` operator to initialize multiple sensors at once.
Managing Power
The `myCodeCell.Run()` function is crucial for power management. This function should be called within the `loop()` function to handle battery status and ensure optimal power usage.
Function Behavior:
Reading Sensor Data
After initializing the sensors, you can read their data using various functions provided by the library. Here's a quick rundown of the available functions:
Light Sensor Functions:
Motion Sensor Functions:
Example Usage:
Sleep, Power-Saving, Diagnostic & LED Functions
The CodeCell includes several functions to manage sleep and power-saving modes:
You've now taken your first steps with CodeCell. Dive deeper into the library examples, explore sensor integrations, and start bringing your innovative projects to life with CodeCell!
In this guide, we will explore how to configure the CodeCell's ESP32-C3 to be used as a WiFi remote, communicating between two devices.
The CodeCell's ESP32-C3 comes with WiFi capability, allowing it to communicate wirelessly. Using ESP-NOW, we can establish direct device-to-device communication with minimal setup. This guide will demonstrate how to pair two devices, using one as a sensor-based remote and the other to receive and act on the transmitted data.
In this example, we will pair two CodeCell devices. Device 1 will gather sensor data and send it to Device 2 via WiFi using the ESP-NOW protocol. We'll start with a simple setup where the proximity sensor on Device 1 controls the onboard LED on Device 2. In the second example, Device 1 will send angular data, and Device 2 will process the data to adjust motor speeds.
Before you can establish communication between the two CodeCell devices, you first need to get the MAC address of the receiver. This MAC address will be used in the sender's code to ensure the correct device receives the data.
Follow these steps to obtain the MAC address of the receiver:
XX:XX:XX:XX:XX:XX
. Copy this address, as you'll need it for the sender's code.This example demonstrates how to send proximity sensor data from Device 1 to Device 2, which will use the data to turn on or off its onboard LED.
#include <esp_now.h>
#include <WiFi.h>
#include <CodeCell.h>
CodeCell myCodeCell;
uint8_t receiverMAC[] = { 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX }; // Replace with receiver's MAC address
void setup() {
Serial.begin(115200);
myCodeCell.Init(LIGHT); // Initializes Light Sensing
// Initialize WiFi in Station mode
WiFi.mode(WIFI_STA);
Serial.println(WiFi.macAddress());
// Initialize ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Register peer
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, receiverMAC, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
}
void loop() {
if (myCodeCell.Run(10)) {
uint16_t ProxRead = (myCodeCell.Light_ProximityRead()) >> 4; // Get Proximity Value and Divide by 16
Serial.println(ProxRead);
esp_err_t result = esp_now_send(receiverMAC, (uint8_t *)&ProxRead, sizeof(ProxRead));
if (result == ESP_OK) {
Serial.println("Data sent successfully");
} else {
Serial.println("Sending Error");
}
}
}
#include <esp_now.h>
#include <WiFi.h>
#include <CodeCell.h>
CodeCell myCodeCell;
void setup() {
Serial.begin(115200);
myCodeCell.Init(LIGHT); // Initializes Light Sensing
// Initialize WiFi in Station mode
WiFi.mode(WIFI_STA);
Serial.println(WiFi.macAddress());
// Initialize ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Register the receive callback
esp_now_register_recv_cb(onDataRecv);
}
// Receive callback function
void onDataRecv(const esp_now_recv_info *recvInfo, const uint8_t *incomingData, int len) {
uint16_t Remote_Value;
memcpy(&Remote_Value, incomingData, sizeof(Remote_Value));
Serial.println(Remote_Value);
myCodeCell.LED(0, Remote_Value, 0); // Control onboard LED brightness
}
void loop() {
// Nothing to do here
}
In this second example, we connect two motors with a two DriveCells to the receiver. Device 1 reads angular data from its motion sensors and sends it to Device 2, which adjusts the speed of two motors based on the received data.
If you are using different devices for this example, remember to read the new MAC address of the receiver and replace the placeholder MAC address in the sender's code.
#include <esp_now.h>
#include <WiFi.h>
#include <CodeCell.h>
CodeCell myCodeCell;
uint8_t receiverMAC[] = {0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX}; // Replace with receiver's MAC address
int Roll_Control = 0;
float Roll = 0.0;
float Pitch = 0.0;
float Yaw = 0.0;
void setup() {
Serial.begin(115200);
myCodeCell.Init(MOTION_ROTATION); // Initialize motion sensing
// Initialize WiFi in Station mode
WiFi.mode(WIFI_STA);
Serial.println(WiFi.macAddress());
// Initialize ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Register peer
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, receiverMAC, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
}
void loop() {
if (myCodeCell.Run(10)) {
myCodeCell.Motion_RotationRead(Roll, Pitch, Yaw);
Roll = Roll + 180;
Roll = (Roll * 100) / 180;
Roll = constrain(Roll, 0, 200) / 2;
Roll_Control = (uint8_t)Roll;
Serial.println(Roll_Control);
esp_now_send(receiverMAC, (uint8_t *)&Roll_Control, sizeof(Roll_Control));
}
}
#include <esp_now.h>
#include <WiFi.h>
#include <CodeCell.h>
#include <DriveCell.h>
#define IN1_pin1 2
#define IN1_pin2 3
#define IN2_pin1 5
#define IN2_pin2 6
CodeCell myCodeCell;
DriveCell Motor1(IN1_pin1, IN1_pin2);
DriveCell Motor2(IN2_pin1, IN2_pin2);
void setup() {
Serial.begin(115200);
myCodeCell.Init(LIGHT); // Initialize Light Sensing
Motor1.Init();
Motor2.Init();
// Initialize WiFi in Station mode
WiFi.mode(WIFI_STA);
Serial.println(WiFi.macAddress());
// Initialize ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Register the receive callback
esp_now_register_recv_cb(onDataRecv);
}
void onDataRecv(const esp_now_recv_info *recvInfo, const uint8_t *incomingData, int len) {
int Roll_Speed = 0;
memcpy(&Roll_Speed, incomingData, sizeof(Roll_Speed));
if (Roll_Speed > 50) {
Motor1.Drive(1, Roll_Speed);
Motor2.Drive(1, Roll_Speed);
} else {
Roll_Speed = 100 - Roll_Speed;
Motor1.Drive(0, Roll_Speed);
Motor2.Drive(0, Roll_Speed);
}
Serial.println(Roll_Speed);
}
void loop() {
if (myCodeCell.Run(10)) {}
}
By following these examples, you can configure two CodeCell devices to communicate over WiFi using ESP-NOW. The examples highlight how to send proximity and angular data between devices and utilize the data for real-time control of LEDs and motors.
Feel free to expand on these projects by incorporating more sensors or additional features to enhance the functionality of your remote system!
In this build, we'll explore how to configure the CodeCell's ESP32-C3 to use Google's Gemini AI for Arduino prompt-based interactions. You'll learn how to send a prompt via the Serial Monitor and, in a second example, how the CodeCell can automatically trigger a joke based on proximity sensing. This project is ideal for anyone looking to add AI capabilities to their IoT projects.
In this example, we use Google’s Gemini model for generating content based on user input or sensor data. Through out this tutorial we will use and modify the code example made by 'techiesms' - Watch the full tutorial here.
With the ESP32-C3's WiFi capabilities, you can make HTTP requests to Google’s Gemini API, allowing real-time interaction with the AI. Whether you’re asking for text responses or generating creative outputs like jokes, this integration is straightforward to implement.
In the first example, you’ll send prompts directly via the Serial Monitor, and the CodeCell will send this input to Google Gemini AI for processing. The AI's response is printed back to the Serial Monitor, limited by 100 tokens. In the second example, the CodeCell’s proximity sensor will trigger a prompt to the AI, asking it to generate a joke when it detects an object. This setup can be used for fun interactive projects where the device responds to its environment using AI-based content.
Before we integrate the Gemini AI into our ESP32-C3 setup, we first need to generate an API key and test it. Follow the steps below to create your API key and then you can also test it using a software like Postman.
Now that we have the API key, we can test it using the Postman application. Postman is a free tool that allows you to make HTTP requests and see the responses.
https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=YOUR_API_KEY
Once you’ve entered the URL, we need to set up the request headers and body.
{
"contents": [
{
"parts": [
{
"text": "Who are you?"
}
]
}
],
"generationConfig": {
"maxOutputTokens": 100
}
}
In this example, we are asking the AI a simple question: "Who are you?" and setting the maximum number of tokens to 100. Tokens control the length of the response generated by the AI. If you lower the token limit (e.g., 20 tokens), the response will be shorter. You can experiment with different values for maxOutputTokens
to see how it affects the response length.
"I am a large language model trained by Google."
Once you've generated and verified that the API works, you can proceed with the next step: integrating this API into your CodeCell project.
Below is the example code to get you started. In this example, the AI will respond to text prompts you send via the Serial Monitor. Remember to replace the placeholders with your WiFi credentials and Gemini API token.
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <CodeCell.h>
CodeCell myCodeCell;
const char* ssid = "SSID"; //Enter your SSID
const char* password = "PASSWORD"; //Enter your password
const char* Gemini_Token = ""; //Enter your Gemini token
const char* Gemini_Max_Tokens = "100";
String res = "";
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.disconnect();
while (!Serial);
// Wait for WiFi connection
WiFi.begin(ssid, password);
Serial.print("Connecting to ");
Serial.println(ssid);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
while (!Serial.available());
while (Serial.available()) {
char add = Serial.read();
res += add;
delay(1);
}
int len = res.length();
res = res.substring(0, len - 1);
res = "\"" + res + "\"";
HTTPClient https;
if (https.begin("https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=" + String(Gemini_Token))) {
https.addHeader("Content-Type", "application/json");
String payload = "{\"contents\": [{\"parts\":[{\"text\":" + res + "}]}],\"generationConfig\": {\"maxOutputTokens\": " + String(Gemini_Max_Tokens) + "}}";
int httpCode = https.POST(payload);
if (httpCode == HTTP_CODE_OK) {
String response = https.getString();
DynamicJsonDocument doc(1024);
deserializeJson(doc, response);
String answer = doc["candidates"][0]["content"]["parts"][0]["text"];
answer.trim();
Serial.println(answer);
} else {
Serial.printf("[HTTPS] POST failed, error: %s\n", https.errorToString(httpCode).c_str());
}
https.end();
} else {
Serial.printf("[HTTPS] Unable to connect\n");
}
res = "";
}
This example uses the CodeCell's proximity sensor to trigger a prompt when an object is detected nearby. The AI will respond with a joke.
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <CodeCell.h>
CodeCell myCodeCell;
const char* ssid = "SSID"; //Enter your SSID
const char* password = "PASSWORD"; //Enter your password
const char* Gemini_Token = ""; //Enter your Gemini token
const char* Gemini_Max_Tokens = "100";
String res = "";
void setup() {
Serial.begin(115200);
myCodeCell.Init(LIGHT); // Initializes proximity sensing
WiFi.mode(WIFI_STA);
WiFi.disconnect();
while (!Serial);
WiFi.begin(ssid, password);
Serial.print("Connecting to ");
Serial.println(ssid);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
if (myCodeCell.Run(10)) {
uint16_t proximity = myCodeCell.Light_ProximityRead();
if (proximity > 100) {
Serial.println("Here's a new joke...");
myCodeCell.LED(0, 0xFF, 0); // Set LED to Green when proximity is detected
res = "\"Tell me a unique joke\"";
HTTPClient https;
if (https.begin("https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=" + String(Gemini_Token))) {
https.addHeader("Content-Type", "application/json");
String payload = "{\"contents\": [{\"parts\":[{\"text\":" + res + "}]}],\"generationConfig\": {\"maxOutputTokens\": " + String(Gemini_Max_Tokens) + "}}";
int httpCode = https.POST(payload);
if (httpCode == HTTP_CODE_OK) {
String response = https.getString();
DynamicJsonDocument doc(1024);
deserializeJson(doc, response);
String answer = doc["candidates"][0]["content"]["parts"][0]["text"];
answer.trim();
Serial.println(answer);
} else {
Serial.printf("[HTTPS] POST failed, error: %s\n", https.errorToString(httpCode).c_str());
}
https.end();
} else {
Serial.printf("[HTTPS] Unable to connect\n");
}
res = "";
}
}
}
This project showcases how to integrate AI responses into your CodeCell projects using Google’s Gemini API. By leveraging the ESP32-C3’s WiFi capabilities, you can create interactive devices that react to user input or environmental factors, making your IoT builds smarter and more engaging.
Experiment with the code and customize the prompts to suit your projects!
In this build, we'll explore how to configure the CodeCell's onboard LED light using the Espalexa library, which allows Alexa to control devices like smart lights. We'll walk you through the process of connecting the CodeCell to your Wi-Fi, setting up the Espalexa library, and enabling voice control for the onboard LED through Alexa.
The Espalexa library simplifies Alexa integration for ESP32 projects. It creates a virtual smart light, which Alexa can control via voice commands, without needing complex setup or cloud services. By using this library, your CodeCell can function as a smart device, like a light bulb, that Alexa can turn on, off, or dim.
In this project, the CodeCell is set up to connect to your Wi-Fi network. Once connected, Alexa can control the onboard LED light using voice commands, whether it's fully on (green) or off (no color).
Below is the example code to get you started. Update the Wi-Fi credentials with your network details, and follow the comments in the code to understand each step.
#include <Espalexa.h>
#include <WiFi.h>
#include <CodeCell.h>
CodeCell myCodeCell;
// WiFi credentials
const char* ssid = "SSID"; //Change to your SSID
const char* password = "PASSWORD"; // Change to your password
// Alexa object
Espalexa espalexa;
// Function to handle Alexa commands
void alexaCallback(uint8_t brightness) {
// Handle brightness (or ON/OFF) commands here
if (brightness == 255) {
myCodeCell.LED(0, 0xFF, 0); // Full brightness, green light
} else if (brightness == 0) {
myCodeCell.LED(0, 0, 0); // Turn off the LED
}
}
void setup() {
// Initialize serial for debugging
Serial.begin(115200);
myCodeCell.Init(LIGHT); /*Initializes Light Sensing*/
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected");
// Add a device to Alexa
espalexa.addDevice("MyLED", alexaCallback);
// Start Espalexa
espalexa.begin();
}
void loop() {
espalexa.loop(); // Handle Alexa requests
}
After uploading the code and connecting the CodeCell to Wi-Fi, the next step is to add the device to your Alexa app. Follow these steps to pair it with Alexa:
With these steps, your CodeCell's onboard LED is now fully integrated into your smart home setup, and you can control it with Alexa voice commands or the Alexa app!
alexaCallback()
function to use different colors based on Alexa’s brightness level. You can use RGB values to create various effects.This project demonstrates how to integrate the CodeCell with Alexa using the Espalexa library to control the onboard LED light. By following this example, you can easily build voice-activated projects with CodeCell, bringing IoT capabilities into your hands!
Get creative with the customization options and bring more of your projects to life with Alexa integration!
In this build, we'll explore how to use the CodeCell's onboard proximity sensor to detect depth gestures and control two FlatFlaps, varying their angles based on the proximity values. This project demonstrates a unique way to create interactive robots, actuators, motors or light that respond to hand movements.
The CodeCell is equipped with a VCNL4040 proximity sensor that can measure distances up to 20 cm. By using an infrared light, the sensor detects objects within its range, measuring the reflection of emitted IR light to approximate distance. This allows you to create responsive behaviors based on how close an object is, making it ideal for interactive gestures.
Depth gestures are based on the proximity data from the CodeCell's onboard sensor. By moving your hand or other objects closer or further from the sensor, you can create dynamic inputs that drive various actions. In this project, the proximity data is used to control the angle of two FlatFlaps, which are connected to two DriveCells (H-bridge drivers).
In this example, the CodeCell continuously reads proximity data and adjusts the angle of two FlatFlaps based on how close the object is. As the object moves closer or further, the angle of the FlatFlaps changes, demonstrating a simple yet effective method for depth gesture-based control.
The two FlatFlaps, are soldered to two DriveCells (H-bridge drivers), which are pin to pin compatible with the CodeCell. These components are then connected on 3D printed mount, to create a cute little Flappy-Bot! Don't forget to add a googly-eye to give it more personality!
Below is the example code to get you started. Ensure your CodeCell is properly connected via USB-C, and the FlatFlaps are connected to the two DriveCells. Follow the comments in the code to understand each step.
#include <CodeCell.h>
#include <DriveCell.h>
#define IN1_pin1 2
#define IN1_pin2 3
#define IN2_pin1 5
#define IN2_pin2 6
DriveCell FlatFlap1(IN1_pin1, IN1_pin2);
DriveCell FlatFlap2(IN2_pin1, IN2_pin2);
CodeCell myCodeCell;
void setup() {
Serial.begin(115200); // Set Serial baud rate to 115200. Ensure Tools/USB_CDC_On_Boot is enabled if using Serial.
myCodeCell.Init(LIGHT); // Initializes Light Sensing
FlatFlap1.Init();
FlatFlap2.Init();
FlatFlap1.Tone();
FlatFlap2.Tone();
}
void loop() {
if (myCodeCell.Run(10)) {
// Runs every 100ms
uint16_t proximity = myCodeCell.Light_ProximityRead();
Serial.println(proximity);
if (proximity < 100) {
// If proximity is detected, the FlatFlaps flap
FlatFlap1.Run(1, 100, 400);
FlatFlap2.Run(1, 100, 400);
} else {
// Adjust FlatFlap angle based on proximity
proximity = proximity - 100;
proximity = proximity / 10;
if (proximity > 100) {
proximity = 100;
}
FlatFlap1.Drive(0, proximity);
FlatFlap2.Drive(0, proximity);
}
}
}
This project shows how to use the CodeCell's proximity sensor for depth gestures, driving the angles of FlatFlaps based on object distance. Experiment with the code, customize the parameters, and bring your own flappy bot to life!
In this guide, we'll explore how to configure the CodeCell's onboard motion sensor to try and guess the personal activate you're doing, and display it on an OLED screen. Its meant to track different states such as walking, running, cycling, climbing stairs and driving!
The CodeCell's motion sensor is capable of categorizing various personal activities based on movement patterns. Based on these patterns the BNO085 sensor will try to guess which activity is being performed. These activities include walking, running, cycling, driving and more.
The CodeCell library makes it easy for you to directly read the activity without any complex code.
In this example, the CodeCell continuously monitors the BNO085's personal activity guess. The activity with the highest chance is then displayed on an OLED screen using the Adafruit SSD1306 library. This setup is ideal for creating wearable activity monitors or fitness trackers that provide real-time feedback on physical activities.
Note that some activities might take between 10-30 seconds to start getting recognized, as it will mainly depend on orientation of the CodeCell and where it is mounted.
Below is the example code to get you started. Make sure your CodeCell is connected via USB-C and your OLED display is wired correctly to the CodeCell’s lower side, using its ground, 3V3, and I2C pins (SDA and SCL).
Follow the comments in the code to understand each step.
#include <CodeCell.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
CodeCell myCodeCell;
/* Configure the OLED Display */
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C // Address of the OLED display
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int read_timer = 0;
void setup() {
Serial.begin(115200); // Set Serial baud rate to 115200. Ensure Tools/USB_CDC_On_Boot is enabled if using Serial.
myCodeCell.Init(MOTION_ACTIVITY); // Initializes activity sensing.
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.display();
delay(2000);
}
void loop() {
if (myCodeCell.Run(10)) {
if (read_timer < 10) {
read_timer++;
} else {
// Update every 1 sec
read_timer = 0;
display.clearDisplay();
display.setCursor(32, 16);
display.print(F("Activity: "));
display.setCursor(32, 24);
switch (myCodeCell.Motion_ActivityRead()) {
case 1:
display.print("Driving");
break;
case 2:
display.print("Cycling");
break;
case 3:
case 6:
display.print("Walking");
break;
case 4:
display.print("Still");
break;
case 5:
display.print("Tilting");
break;
case 7:
display.print("Running");
break;
case 8:
display.print("Stairs");
break;
default:
display.print("Reading..");
break;
}
display.display();
}
}
}
This project demonstrates how to use the CodeCell’s motion sensor to monitor personal activities and display the results on an OLED screen. This basic setup provides a foundation for developing more advanced activity monitoring systems.
Experiment with the code and settings to create your own personalized wearable!
In this guide, we'll explore how to use the CodeCell's onboard motion sensor to measure step counts and display these counts on an OLED display, making it easy to turn CodeCell into your own Pedometer or even fitness tracker!
CodeCell is equipped with a BNO085 motion sensor that uses fused the data from an accelerometer, gyroscope and magnetometer, to track specific movement patterns and determine if a step was made. Each step is then added to a counter, and the CodeCell library help you easily reads these step counts.
In this example, the CodeCell continuously monitors for steps and updates the count. This count is then displayed on an OLED screen using the Adafruit SSD1306 library.
Below is the example code to get you started. Ensure your CodeCell is properly connected via USB-C and your OLED display is correctly wired to the CodeCell's lower side. There you can use its ground, 3V3 and I2C pins (SDA and SCL).
Follow the comments in the code to understand each step.
#include <CodeCell.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
CodeCell myCodeCell;
/* Configure the OLED Display */
#define SCREEN_WIDTH 64 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C // Address of the OLED display
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
uint16_t step_counter = 0;
void setup() {
Serial.begin(115200); // Set Serial baud rate to 115200. Ensure Tools/USB_CDC_On_Boot is enabled if using Serial.
myCodeCell.Init(MOTION_STEP_COUNTER); // Initializes step counting and activity sensing.
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println("Display Error");
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.display();
delay(2000);
}
void loop() {
if (myCodeCell.Run(10)) { //Run every 10Hz
step_counter = myCodeCell.Motion_StepCounterRead(); //Read step counter
display.clearDisplay();
display.setCursor(32, 16); // Start at top-left corner
display.print(F("Steps: "));
display.print(step_counter);
display.display(); //Update Display
}
}
This project demonstrates how to use the CodeCell’s motion sensor as a pedometer and display the step counts on an OLED screen. Experiment with the code, to create your own wearable fitness device and check out the CodeCell GitHub Repository for more code examples and technical documentation!
In this guide, we'll explore how to use the CodeCell to control a servo motor. We will also see how we can control the servo's angular position using the CodeCell's angular position, which is especially useful for robotic applications like gimbals or angular stability control.
A servo motor is a rotary actuator that allows for precise control of angular position. It consists of a motor coupled with gears and a sensor for position feedback, and it is commonly used in robotics, automation, and stabilization applications.
CodeCell is equipped with a BNO085 motion sensor that fuses data from an accelerometer, gyroscope, and magnetometer to compute rotation vectors. These vectors are processed by CodeCell to obtain roll, pitch, and yaw angles based on the device's orientation in space.
In this example, our CodeCell continuously monitors the pitch angle to control the position of a servo motor, allowing it to respond dynamically to changes in orientation. The pitch value is used to set the servo motor's position, enabling it to rotate based on how you tilt the device.
Below is an example code snippet to get you started. Ensure your CodeCell is properly connected via USB-C. Also, verify that your servo motor can be driven via USB-C power (CodeCell can deliver up to 500mA via USB-C and up to 1500mA when powered by a battery). Adjust the angular limits in the code accordingly.
For this example, you need to install the 'ESP32Servo' library to control the servo motor with your CodeCell. Follow the comments in the code to understand each step.
#include <codecell.h>
#include <ESP32Servo.h>
CodeCell myCodeCell;
Servo myservo;
float Roll = 0.0;
float Pitch = 0.0;
float Yaw = 0.0;
int servo_angle = 0;
void setup() {
Serial.begin(115200); // Set Serial baud rate to 115200. Enable Tools/USB_CDC_On_Boot if using Serial
myCodeCell.Init(MOTION_ROTATION); // Initializes rotation sensing
myservo.attach(1); // Attaches the servo on pin 1 to the servo object
}
void loop() {
if (myCodeCell.Run(10)) {
// Read rotation angles from the BNO085 sensor
myCodeCell.Motion_RotationRead(Roll, Pitch, Yaw);
// Convert the pitch angle to a servo angle
servo_angle = abs((int)Pitch);
servo_angle = (180 - servo_angle);
// Limit the servo angle to the range 0-60 degrees
if (servo_angle > 60) {
servo_angle = 60;
} else if (servo_angle < 0) {
servo_angle = 0;
}
else{
//Skip
}
Serial.println(servo_angle); // Print the servo angle for debugging
myservo.write(servo_angle); // Set the servo position
}
}
This basic functionality can be expanded to create more complex interactions, such as:
servo_angle
in the code. In this example, we use a 60-degree range micro-servo. Some servo motors are not mechanically linear, so you might need to compensate for angular-mechanical errors.This project demonstrates how to control a servo motor with CodeCell using its motion-sensing capabilities. Experiment with the code, build your own projects, and check out the CodeCell GitHub Repository for more code examples and technical documentation!
In this guide, we'll explore how to use the CodeCell's onboard motion sensor to detect taps. This project demonstrates how to use tap detection for interactive controls, making it perfect for creating responsive actions with a simple tap on the device.
CodeCell is is equipped with a BNO085 motion sensor that fuses the data from an accelerometer, gyroscope and magnetometer, to track specific movement patterns and determine if a tap was made, making it ideal for interactive controls like toggling lights, triggering sound effects, or other actions based on a simple tap gesture.
In the first example, we setup our CodeCell to continuously check for a tap. When a tap is detected, the onboard LED lights up in yellow for one second. You can expand on this basic functionality to create more complex interactions, such as controlling multiple LEDs, motors, or other connected devices based on tap inputs.
Make sure your CodeCell is properly connected via USB-C, and follow the comments in the code to understand each step.
#include <CodeCell.h>
CodeCell myCodeCell;
void setup() {
Serial.begin(115200); // Set Serial baud rate to 115200. Ensure Tools/USB_CDC_On_Boot is enabled if using Serial
myCodeCell.Init(MOTION_TAP_DETECTOR); // Initializes tap detection sensing
}
void loop() {
if (myCodeCell.Run(10)) {
// Runs every 100ms to check for taps
if (myCodeCell.Motion_TapRead()) {
// If a tap is detected, shine the LED yellow for 1 second
myCodeCell.LED(0xA0, 0x60, 0x00); // Set LED to yellow
delay(1000); // Keep the LED on for 1 second
}
}
}
In this next example, we use a CoilCell to flip its polarity, and actuate a flip-dot. This expands the interactivity by using tap detection to control external devices, creating a more dynamic response.
#include <CoilCell.h>
#include <CodeCell.h>
#define IN1_pin1 5
#define IN1_pin2 6
CoilCell myCoilCell(IN1_pin1, IN1_pin2);
CodeCell myCodeCell;
void setup() {
Serial.begin(115200); // Set Serial baud rate to 115200. Ensure Tools/USB_CDC_On_Boot is enabled if using Serial.
myCodeCell.Init(MOTION_TAP_DETECTOR); // Initializes tap detection sensing.
myCoilCell.Init(); // Initializes the CoilCell.
myCoilCell.Tone(); // Plays a tone to confirm initialization.
}
void loop() {
if (myCodeCell.Run(10)) {
// Runs every 100ms to check for taps.
if (myCodeCell.Motion_TapRead()) {
// If a tap is detected, shine the LED yellow and flip the CoilCell's polarity.
myCodeCell.LED(0xA0, 0x60, 0x00); // Set LED to yellow.
myCoilCell.Toggle(100); // Toggle the CoilCell's polarity.
delay(1000); // Delay to keep the LED on and polarity flipped for 1 second.
}
}
}
Experiment with the code, customize the responses, and check out the CodeCell GitHub Repository for more code examples and technical documentation!
Join our Community ~ Be the first to know about new products and get exciting deals!
© 2025 Microbots.