// simple project using Arduino UNO and 128x64 OLED Display, showing a message with the fireworks animation
// created by upir, 2022
// youtube channel: https://www.youtube.com/channel/UCWHHWV_tkafsHNZ65V64sNQ
// youtube full tutorial: https://youtu.be/hIFDcksXgBk
// image2cpp (convert images into C code): https://javl.github.io/image2cpp/
// u8g fonts (fonts available for u8g library): https://nodemcu-build.com/u8g-fonts.php
// u8g documentation: https://github.com/olikraus/u8glib/wiki/userreference#getstrwidth
// Photopea (online Photoshop-like tool): https://www.photopea.com/
// Wokwi starting project: https://wokwi.com/arduino/projects/300867986768527882
// Transparent display buy: https://a.aliexpress.com/_mKGmhKg
// Arduino uno: http://store.arduino.cc/products/arduino-uno-rev3
// Arduino breadboard prototyping shield: https://www.adafruit.com/product/2077
// select SPI or IIC connection from the list below, or change it to match your display settings
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI
//U8GLIB_SSD1306_128X64 u8g(13, 11, 8, 9, 10); // SPI connection
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);
//This line contain direction logo/bitmap
#define direction_width 9
#define direction_height 13
static const unsigned char direction_bits[] U8X8_PROGMEM = {
0x10, 0xfe, 0x10, 0xfe, 0x10, 0xfe, 0x10, 0xfe, 0x38, 0xfe, 0x38, 0xfe,
0x38, 0xfe, 0x7c, 0xfe, 0x7c, 0xfe, 0x7c, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe
};
const int centreX = 50;
const int centreY = 32;
const int radius = 20;
int xn, yn, xe, ye, xs, ys, xw, yw;
//offset setting for Display N-E-S-W
int offsetRadius = 5;
int offsetCentreX = -2;
int offsetCentreY = 2;
//offset setting for North
float offsetCalibration = -0.5;
float angle = 0;//(heading * 180 / M_PI);
float direction = 55;
int control = 0; // 0 - OFF, 1 - STOP, 2 - MANUAL, 3 - ANGLE, 4 - ANCHOR
int prevControl = 0;
char* controlName[] = {"OFF", "STOP", "MANUAL", "ANGLE", "ANCHOR"};
int controlOffset[] = {9,6,0,3,0};
int mode = 1, menu = 1, menuOn;
int lastMode = 0, lastMenu = 0;
void setup() {
//u8g.setFont(u8g_font_tpssb);
u8g2.begin();
u8g2.enableUTF8Print();
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
}
void loop() {
int mode = digitalRead(7);
int menu = digitalRead(6);
if (mode != lastMode) {
if (mode == LOW) {
control++;
if (control > 4) {
control = 0;
}
}
lastMode = mode;
}
else {
if (menu != lastMenu) {
if (menu == LOW) {
if (control == 0) { // Enable menu if OFF
menuOn = 1;
}
else { // Anchor
control = 4;
}
}
lastMenu = menu;
}
}
float heading = 35.0;
// How to get the magnetic declination angle
// is available in the article https://bit.ly/3Zd6e2z
float declination = -0.7;
heading += declination;
// Correct for when signs are reversed.
if (heading < 0)
heading += 2 * PI;
// Check for wrap due to addition of declination.
if (heading > 2 * PI)
heading -= 2 * PI;
//Serial.println(angle);
// angle = angle + 17; // Boat angle
if (angle > 360) {
angle = 0;
}
u8g2.firstPage();
do {
//calculate X, Y position of West
xw = ((radius + offsetRadius) * -cos((angle - 0) * 3.14 / 180)) + centreX + offsetCentreX;
yw = ((radius + offsetRadius) * sin((angle - 0) * 3.14 / 180)) + centreY + offsetCentreY;
//calculate X, Y position of North
xn = ((radius + offsetRadius) * -cos((angle - 90) * 3.14 / 180)) + centreX + offsetCentreX;
yn = ((radius + offsetRadius) * sin((angle - 90) * 3.14 / 180)) + centreY + offsetCentreY;
//calculate X, Y position of East
xe = ((radius + offsetRadius) * -cos((angle - 180) * 3.14 / 180)) + centreX + offsetCentreX;
ye = ((radius + offsetRadius) * sin((angle - 180) * 3.14 / 180)) + centreY + offsetCentreY;
//calculate X, Y position of South
xs = ((radius + offsetRadius) * -cos((angle - 270) * 3.14 / 180)) + centreX + offsetCentreX;
ys = ((radius + offsetRadius) * sin((angle - 270) * 3.14 / 180)) + centreY + offsetCentreY;
//Draw Circle
u8g2.drawCircle(centreX, centreY, radius, U8G2_DRAW_ALL);
//Show Direction Icon, by tutorial here https://bit.ly/3VAOlrm
u8g2.drawXBMP(46, 25, direction_width, direction_height, direction_bits);
//Show angle value on OLED
u8g2.setFont(u8g2_font_6x10_tf);
u8g2.setCursor(90, 32);
u8g2.print((String(angle, 0) + "\xb0"));
if (control == 0) {
u8g2.drawStr(0, 62, "MENU");
}
else {
u8g2.drawStr(0, 62, "ANCHOR");
}
u8g2.drawStr(100, 62, "MODE");
u8g2.drawBox(89,0,38,12);
u8g2.setFontMode(0);
u8g2.setDrawColor(0);
u8g2.drawStr(90+controlOffset[control], 8, controlName[control]);
//Draw points of the compass every angle
u8g2.setFontPosCenter();
u8g2.setDrawColor(1);
u8g2.setBitmapMode(0);
u8g2.drawStr(xn, yn, "N");
u8g2.drawStr(xe, ye, "E");
u8g2.drawStr(xs, ys, "S");
u8g2.drawStr(xw, yw, "W");
} while (u8g2.nextPage());
delay(100);
}