Can the Arduino Giga tell your future?
Pretend for a moment you’ve been captured by a motley band of rebel physicists bent on building a time machine.
You’ve been locked in an electronics shop and told you can’t come out until you have a working prototype built.
This is going to be a problem, you have a dentist appointment at 3:15pm, and if you miss it, rescheduling those is a nightmare. That gives you 45 minutes to build a working time machine prototype.
Instead of building a time machine, you’ll build something to distract them, while you sneak out to your dentist appointment.
You’ll build a Probabilistic Time State Engine…basically, it’s a magic 8-ball, but instead of an 8-ball, you’ll use the 3d printed cat…
Arduino Code
You’ll need a ChatGPT API key to make this work. It’s pretty easy to set up a developer account with OpenAI and get your key, here’s how.
The ChatGPT library “ChatGPTuino” used in this example is here. It is still very much under development.
#include "Arduino_BMI270_BMM150.h"
#include "Arduino_H7_Video.h"
#include "lvgl.h"
#include "lv_conf.h"
#include <ChatGPTuino.h>
#include <WiFi.h>
#include "credentials.h" // Network name, password, and private API key
Arduino_H7_Video Display(800, 480, GigaDisplayShield); /* Arduino_H7_Video Display(1024, 768, USBCVideo); */
BoschSensorClass imu(Wire1);
const int TOKENS = 100; // How lengthy a response you want, every token is about 3/4 a word
const int NUM_MESSAGES = 20;
ChatGPTuino chat{ TOKENS, NUM_MESSAGES }; // Will store and send your most recent messages (up to NUM_MESSAGES)
const char *model = "gpt-4o"; // OpenAI Model being used
const int fadeAmount = 5;
static lv_style_t style_main;
static lv_style_t style_shadow;
lv_obj_t *shadow_label;
lv_obj_t *main_label;
volatile int text_opacity = 255;
enum States {
FORTUNE_DISPLAYED,
GET_FORTUNE,
REVEAL_FORTUNE
} state = FORTUNE_DISPLAYED;
void setup() {
Serial.begin(115200);
Display.begin();
imu.begin();
//Set Background Black
lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x000000), LV_PART_MAIN);
// Make a label
/*Create a style for the shadow*/
lv_style_init(&style_shadow);
lv_style_set_text_opa(&style_shadow, LV_OPA_30);
lv_style_set_text_color(&style_shadow, lv_color_hex(0xef7422));
lv_style_set_text_font(&style_shadow, &lv_font_montserrat_48);
lv_style_init(&style_main);
lv_style_set_text_color(&style_main, lv_color_white());
lv_style_set_text_font(&style_main, &lv_font_montserrat_48);
/*Create a label for the shadow first (it's in the background)*/
shadow_label = lv_label_create(lv_screen_active());
lv_obj_add_style(shadow_label, &style_shadow, 0);
/*Create the main label*/
main_label = lv_label_create(lv_screen_active());
lv_obj_add_style(main_label, &style_main, 0);
// WiFi Setup
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Initialize messages array
chat.init(key, model);
// Add user message to messages array
chat.putMessage(userMessage, strlen(userMessage));
// Add system message to messages array
chat.putMessage(systemMessage, strlen(systemMessage), Sys);
lv_label_set_text(main_label, "Shake me for possibilities");
/*Set the same text for the shadow label*/
lv_label_set_text(shadow_label, lv_label_get_text(main_label));
/*Position the main label*/
lv_obj_align(main_label, LV_ALIGN_CENTER, 0, 0);
/*Shift the second label down and to the right by 2 pixel*/
lv_obj_align_to(shadow_label, main_label, LV_ALIGN_TOP_LEFT, 6, 6);
// Print response
Serial.println(chat.getLastMessageContent());
}
uint8_t rotation = 0;
void loop() {
lv_timer_handler();
float x, y, z;
static int count = 0;
if (imu.accelerationAvailable() && (state == FORTUNE_DISPLAYED)) {
imu.readAcceleration(x, y, z);
if (z < 0.8 && z > -0.8) {
text_opacity = text_opacity - fadeAmount;
if (text_opacity <= 0) {
text_opacity = 0;
chat.putMessage(userMessage, strlen(userMessage));
state = GET_FORTUNE;
}
lv_style_set_text_opa(&style_shadow, text_opacity);
lv_style_set_text_opa(&style_main, text_opacity);
lv_obj_align_to(shadow_label, main_label, LV_ALIGN_TOP_LEFT, 6, 6);
lv_obj_report_style_change(NULL);
Serial.print("text_opacity = ");
Serial.println(text_opacity);
}
}
if (state == GET_FORTUNE) {
// Send message array and receive response
chat.getResponse();
Serial.println(chat.getLastMessageContent());
lv_label_set_text(main_label, chat.getLastMessageContent());
/*Set the same text for the shadow label*/
lv_label_set_text(shadow_label, lv_label_get_text(main_label));
lv_obj_align_to(shadow_label, main_label, LV_ALIGN_TOP_LEFT, 6, 6);
text_opacity = 255;
lv_style_set_text_opa(&style_shadow, text_opacity);
lv_style_set_text_opa(&style_main, text_opacity);
lv_obj_report_style_change(NULL);
state = FORTUNE_DISPLAYED;
}
}
credentials.h file:
#ifndef Secret_h #define Secret_h /* Keep all these private */ const char* ssid = "UnderGroundLayer"; // Change to your WiFi Network name const char* password = "MWaHaHaHa7#!"; // Change to your WiFi password const char* key = ""; // Your private API Key see https://bit.ly/OpenAI-Dev to get setup const char *userMessage = "Give me a new fortune."; // User message to ChatGPT const char *systemMessage = "You are a magic 8 ball simulator with a twist. You are funny and snarky, and almost always predict doom or amazing glory. " "Your target audience is physicists. " "You have been loaded onto an embedded device with a small LCD screen. " "You must respond in 20 words or less. Less is fine. " "you need to include newline characters so that the text does not flow over the screen. " "Do not use special characters like umlauts, or apsotrophes either. " "For example: " "You are in\n " "Luck \n " "thoretically"; #endif