This commit is contained in:
2025-05-06 11:17:58 +02:00
parent b11ed673ef
commit 0c2f5f6064

View File

@@ -1,4 +1,4 @@
# interface_application_programming # interface and application programming
For this week I wanna make use of the Oled display on the controller I designed For this week I wanna make use of the Oled display on the controller I designed
![alt text](image.png) ![alt text](image.png)
@@ -102,324 +102,324 @@ A portion of this code was taken from the machining week group project. But what
![alt text](image-11.png) ![alt text](image-11.png)
??? ???
```cpp ```cpp
// simple project using Arduino UNO and 128x64 OLED Display to display a menu // simple project using Arduino UNO and 128x64 OLED Display to display a menu
// created by upir, 2022 // created by upir, 2022
// youtube channel: https://www.youtube.com/upir_upir // youtube channel: https://www.youtube.com/upir_upir
// YOUTUBE VIDEO: https://youtu.be/HVHVkKt-ldc // YOUTUBE VIDEO: https://youtu.be/HVHVkKt-ldc
// WOKWI PROJECT: https://wokwi.com/projects/353101459130291201 // WOKWI PROJECT: https://wokwi.com/projects/353101459130291201
// links from the video: // links from the video:
// Flipper Zero menu - https://docs.flipperzero.one/basics/control#M5BZO // Flipper Zero menu - https://docs.flipperzero.one/basics/control#M5BZO
// WOKWI start project progress bar - https://wokwi.com/projects/300867986768527882 // WOKWI start project progress bar - https://wokwi.com/projects/300867986768527882
// image2cpp - https://javl.github.io/image2cpp/ // image2cpp - https://javl.github.io/image2cpp/
// 128x64 SSD1306 OLED Display: https://s.click.aliexpress.com/e/_DCKdvnh // 128x64 SSD1306 OLED Display: https://s.click.aliexpress.com/e/_DCKdvnh
// Transparent OLED display: https://s.click.aliexpress.com/e/_Dns6eLz // Transparent OLED display: https://s.click.aliexpress.com/e/_Dns6eLz
// Arduino UNO: https://s.click.aliexpress.com/e/_AXDw1h // Arduino UNO: https://s.click.aliexpress.com/e/_AXDw1h
// Arduino UNO MINI: https://store.arduino.cc/products/uno-mini-le // Arduino UNO MINI: https://store.arduino.cc/products/uno-mini-le
// Big OLED Display: https://s.click.aliexpress.com/e/_ADL0T9 // Big OLED Display: https://s.click.aliexpress.com/e/_ADL0T9
// Arduino breadboard prototyping shield: https://s.click.aliexpress.com/e/_ApbCwx // Arduino breadboard prototyping shield: https://s.click.aliexpress.com/e/_ApbCwx
// u8g fonts (fonts available for u8g library): https://nodemcu-build.com/u8g-fonts.php // u8g fonts (fonts available for u8g library): https://nodemcu-build.com/u8g-fonts.php
// u8g documentation: https://github.com/olikraus/u8glib/wiki/userreference // u8g documentation: https://github.com/olikraus/u8glib/wiki/userreference
// Photopea (online Photoshop-like tool): https://www.photopea.com/ // Photopea (online Photoshop-like tool): https://www.photopea.com/
// image2cpp (convert images into C code): https://javl.github.io/image2cpp/ // image2cpp (convert images into C code): https://javl.github.io/image2cpp/
// Push buttons - https://s.click.aliexpress.com/e/_DmXS8B9 // Push buttons - https://s.click.aliexpress.com/e/_DmXS8B9
// Related videos: // Related videos:
// Arduino Parking Sensor - https://youtu.be/sEWw087KOj0 // Arduino Parking Sensor - https://youtu.be/sEWw087KOj0
// Turbo pressure gauge with Arduino and OLED display - https://youtu.be/JXmw1xOlBdk // Turbo pressure gauge with Arduino and OLED display - https://youtu.be/JXmw1xOlBdk
// Arduino Car Cluster with OLED Display - https://youtu.be/El5SJelwV_0 // Arduino Car Cluster with OLED Display - https://youtu.be/El5SJelwV_0
// Knob over OLED Display - https://youtu.be/SmbcNx7tbX8 // Knob over OLED Display - https://youtu.be/SmbcNx7tbX8
// Arduino + OLED = 3D ? - https://youtu.be/kBAcaA7NAlA // Arduino + OLED = 3D ? - https://youtu.be/kBAcaA7NAlA
// Arduino OLED Gauge - https://youtu.be/xI6dXTA02UQ // Arduino OLED Gauge - https://youtu.be/xI6dXTA02UQ
// Smaller & Faster Arduino - https://youtu.be/4GfPQoIRqW8 // Smaller & Faster Arduino - https://youtu.be/4GfPQoIRqW8
#include <Arduino.h> #include <Arduino.h>
#include <U8g2lib.h> #include <U8g2lib.h>
#include <Wire.h> #include <Wire.h>
#include <Graphics.h> #include <Graphics.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//=====================================================================================// //=====================================================================================//
// Struct declarations // Struct declarations
typedef struct struct_message typedef struct struct_message
{ {
int PWMCH1; int PWMCH1;
int PWMCH2; int PWMCH2;
int PWMCH3; int PWMCH3;
int PWMCH4; int PWMCH4;
} struct_message; } struct_message;
struct_message JoystickData; // declare the struct as JoystickData struct_message JoystickData; // declare the struct as JoystickData
struct hardJoystickValues struct hardJoystickValues
{ {
int LXU; // Left joystick X axis up int LXU; // Left joystick X axis up
int LXD; // Left joystick X axis down int LXD; // Left joystick X axis down
int RXU; // Right joystick X axis up int RXU; // Right joystick X axis up
int RXD; // Right joystick X axis down int RXD; // Right joystick X axis down
}; };
hardJoystickValues JoystickDataHard; // declare the struct as JoystickDataHard hardJoystickValues JoystickDataHard; // declare the struct as JoystickDataHard
//=====================================================================================// //=====================================================================================//
//declarations //declarations
void GUITestLoop(); void GUITestLoop();
void MUXSetup(); void MUXSetup();
hardJoystickValues GUIParser(); hardJoystickValues GUIParser();
int analogReadMultiPlexer(int addressA, int addressB, int addressC, int addressD, int pin); int analogReadMultiPlexer(int addressA, int addressB, int addressC, int addressD, int pin);
int mapPot(int normalizedValue); int mapPot(int normalizedValue);
// Controller declarations // Controller declarations
const int MAXPWMVALUE = 1000; const int MAXPWMVALUE = 1000;
const int MINPWMVALUE = 2000; const int MINPWMVALUE = 2000;
// Screen declarations // Screen declarations
const int NUM_ITEMS = 8; // number of items in the list and also the number of screenshots and screenshots with QR codes (other screens) const int NUM_ITEMS = 8; // number of items in the list and also the number of screenshots and screenshots with QR codes (other screens)
const int MAX_ITEM_LENGTH = 20; // maximum characters for the item name const int MAX_ITEM_LENGTH = 20; // maximum characters for the item name
char menu_items [NUM_ITEMS] [MAX_ITEM_LENGTH] = { // array with item names char menu_items [NUM_ITEMS] [MAX_ITEM_LENGTH] = { // array with item names
{ "3D Cube" }, { "3D Cube" },
{ "Battery" }, { "Battery" },
{ "Dashboard" }, { "Dashboard" },
{ "Fireworks" }, { "Fireworks" },
{ "GPS Speed" }, { "GPS Speed" },
{ "Big Knob" }, { "Big Knob" },
{ "Park Sensor" }, { "Park Sensor" },
{ "Turbo Gauge" } { "Turbo Gauge" }
}; };
// note - when changing the order of items above, make sure the other arrays referencing bitmaps // note - when changing the order of items above, make sure the other arrays referencing bitmaps
// also have the same order, for example array "bitmap_icons" for icons, and other arrays for screenshots and QR codes // also have the same order, for example array "bitmap_icons" for icons, and other arrays for screenshots and QR codes
#define BUTTON_UP_PIN JoystickDataHard.LXU // pin for UP button #define BUTTON_UP_PIN JoystickDataHard.LXU // pin for UP button
#define BUTTON_SELECT_PIN buttonRight// pin for SELECT button #define BUTTON_SELECT_PIN buttonRight// pin for SELECT button
#define BUTTON_DOWN_PIN JoystickDataHard.LXD // pin for DOWN button #define BUTTON_DOWN_PIN JoystickDataHard.LXD // pin for DOWN button
#define DEMO_PIN D0 // pin for demo mode, use switch or wire to enable or disable demo mode, see more details below #define DEMO_PIN D0 // pin for demo mode, use switch or wire to enable or disable demo mode, see more details below
int button_up_clicked = 0; // only perform action when button is clicked, and wait until another press int button_up_clicked = 0; // only perform action when button is clicked, and wait until another press
int button_select_clicked = 0; // same as above int button_select_clicked = 0; // same as above
int button_down_clicked = 0; // same as above int button_down_clicked = 0; // same as above
int item_selected = 0; // which item in the menu is selected int item_selected = 0; // which item in the menu is selected
int item_sel_previous; // previous item - used in the menu screen to draw the item before the selected one int item_sel_previous; // previous item - used in the menu screen to draw the item before the selected one
int item_sel_next; // next item - used in the menu screen to draw next item after the selected one int item_sel_next; // next item - used in the menu screen to draw next item after the selected one
int current_screen = 0; // 0 = menu, 1 = screenshot, 2 = qr int current_screen = 0; // 0 = menu, 1 = screenshot, 2 = qr
int demo_mode = 0; // when demo mode is set to 1, it automatically goes over all the screens, 0 = control menu with buttons int demo_mode = 0; // when demo mode is set to 1, it automatically goes over all the screens, 0 = control menu with buttons
int demo_mode_state = 0; // demo mode state = which screen and menu item to display int demo_mode_state = 0; // demo mode state = which screen and menu item to display
int demo_mode_delay = 0; // demo mode delay = used to slow down the screen switching int demo_mode_delay = 0; // demo mode delay = used to slow down the screen switching
bool buttonRight; bool buttonRight;
bool buttonLeft; bool buttonLeft;
void setup() { void setup() {
u8g2.begin(); u8g2.begin();
u8g2.setColorIndex(1); // set the color to white u8g2.setColorIndex(1); // set the color to white
MUXSetup(); // Setup the multiplexer MUXSetup(); // Setup the multiplexer
}
void loop() {
JoystickData.PWMCH1 = mapPot(analogReadMultiPlexer(0, 0, 0, 0, A0)); //Right joystick Y
JoystickData.PWMCH2 = mapPot(analogReadMultiPlexer(1, 0, 0, 0, A0)); // Right joystick X
JoystickData.PWMCH3 = mapPot(analogReadMultiPlexer(0, 0, 0, 1, A0)); // left joystick Y
JoystickData.PWMCH4 = mapPot(analogReadMultiPlexer(1, 0, 0, 1, A0)); // left joystick X
buttonRight = abs(analogReadMultiPlexer(0, 0, 1, 0, A0)/4095); // right button
buttonLeft = abs(analogReadMultiPlexer(1, 0, 1, 0, A0)/4095); // left button
JoystickDataHard = GUIParser();
GUITestLoop();
}
void GUITestLoop(){
// when pin 13 is LOW (DEMO_PIN), enable demo mode
// this could be done either by using a switch
// or simply by connecting the wire between pin 13 and GND
// (those pins are next to each other)
if (digitalRead(DEMO_PIN) == LOW) {
demo_mode = 0; // enable demo mode
}
else {
demo_mode = 0; // disable demo mode
}
if (demo_mode == 1) { // when demo mode is active, automatically switch between all the screens and menu items
demo_mode_delay++; // increase demo mode delay
if (demo_mode_delay > 15) { // after some time, switch to another screen - change this value to make it slower/faster
demo_mode_delay = 0;
demo_mode_state++; // increase counter
if (demo_mode_state >= NUM_ITEMS*3) {demo_mode_state=0;} // jump back to the first screen
} }
if (demo_mode_state % 3 == 0) {current_screen = 0; item_selected = demo_mode_state/3; } // menu screen
else if (demo_mode_state % 3 == 1) {current_screen = 1; item_selected = demo_mode_state/3;} // screenshots screen
else if (demo_mode_state % 3 == 2) {current_screen = 2; item_selected = demo_mode_state/3;} // qr codes screen
} // end demo mode section
if (current_screen == 0) { // MENU SCREEN void loop() {
JoystickData.PWMCH1 = mapPot(analogReadMultiPlexer(0, 0, 0, 0, A0)); //Right joystick Y
JoystickData.PWMCH2 = mapPot(analogReadMultiPlexer(1, 0, 0, 0, A0)); // Right joystick X
JoystickData.PWMCH3 = mapPot(analogReadMultiPlexer(0, 0, 0, 1, A0)); // left joystick Y
JoystickData.PWMCH4 = mapPot(analogReadMultiPlexer(1, 0, 0, 1, A0)); // left joystick X
buttonRight = abs(analogReadMultiPlexer(0, 0, 1, 0, A0)/4095); // right button
buttonLeft = abs(analogReadMultiPlexer(1, 0, 1, 0, A0)/4095); // left button
// up and down buttons only work for the menu screen JoystickDataHard = GUIParser();
if ((BUTTON_UP_PIN == LOW) && (button_up_clicked == 0)) { // up button clicked - jump to previous menu item GUITestLoop();
item_selected = item_selected - 1; // select previous item }
button_up_clicked = 1; // set button to clicked to only perform the action once
if (item_selected < 0) { // if first item was selected, jump to last item
item_selected = NUM_ITEMS-1;
void GUITestLoop(){
// when pin 13 is LOW (DEMO_PIN), enable demo mode
// this could be done either by using a switch
// or simply by connecting the wire between pin 13 and GND
// (those pins are next to each other)
if (digitalRead(DEMO_PIN) == LOW) {
demo_mode = 0; // enable demo mode
}
else {
demo_mode = 0; // disable demo mode
}
if (demo_mode == 1) { // when demo mode is active, automatically switch between all the screens and menu items
demo_mode_delay++; // increase demo mode delay
if (demo_mode_delay > 15) { // after some time, switch to another screen - change this value to make it slower/faster
demo_mode_delay = 0;
demo_mode_state++; // increase counter
if (demo_mode_state >= NUM_ITEMS*3) {demo_mode_state=0;} // jump back to the first screen
} }
}
else if ((BUTTON_DOWN_PIN == LOW) && (button_down_clicked == 0)) { // down button clicked - jump to next menu item if (demo_mode_state % 3 == 0) {current_screen = 0; item_selected = demo_mode_state/3; } // menu screen
item_selected = item_selected + 1; // select next item else if (demo_mode_state % 3 == 1) {current_screen = 1; item_selected = demo_mode_state/3;} // screenshots screen
button_down_clicked = 1; // set button to clicked to only perform the action once else if (demo_mode_state % 3 == 2) {current_screen = 2; item_selected = demo_mode_state/3;} // qr codes screen
if (item_selected >= NUM_ITEMS) { // last item was selected, jump to first menu item
item_selected = 0;
}
}
if ((BUTTON_UP_PIN == HIGH) && (button_up_clicked == 1)) { // unclick } // end demo mode section
button_up_clicked = 0;
}
if ((BUTTON_DOWN_PIN == HIGH) && (button_down_clicked == 1)) { // unclick
button_down_clicked = 0;
}
}
if ((BUTTON_SELECT_PIN == LOW) && (button_select_clicked == 0)) { // select button clicked, jump between screens
button_select_clicked = 1; // set button to clicked to only perform the action once
if (current_screen == 0) {current_screen = 1;} // menu items screen --> screenshots screen
else if (current_screen == 1) {current_screen = 2;} // screenshots screen --> qr codes screen
else {current_screen = 0;} // qr codes screen --> menu items screen
}
if ((BUTTON_SELECT_PIN == HIGH) && (button_select_clicked == 1)) { // unclick
button_select_clicked = 0;
}
// set correct values for the previous and next items
item_sel_previous = item_selected - 1;
if (item_sel_previous < 0) {item_sel_previous = NUM_ITEMS - 1;} // previous item would be below first = make it the last
item_sel_next = item_selected + 1;
if (item_sel_next >= NUM_ITEMS) {item_sel_next = 0;} // next item would be after last = make it the first
u8g2.firstPage(); // required for page drawing mode for u8g library
do {
if (current_screen == 0) { // MENU SCREEN if (current_screen == 0) { // MENU SCREEN
// selected item background // up and down buttons only work for the menu screen
u8g2.drawBitmap(0, 22, 128/8, 21, bitmap_item_sel_outline); if ((BUTTON_UP_PIN == LOW) && (button_up_clicked == 0)) { // up button clicked - jump to previous menu item
item_selected = item_selected - 1; // select previous item
button_up_clicked = 1; // set button to clicked to only perform the action once
if (item_selected < 0) { // if first item was selected, jump to last item
item_selected = NUM_ITEMS-1;
}
}
else if ((BUTTON_DOWN_PIN == LOW) && (button_down_clicked == 0)) { // down button clicked - jump to next menu item
item_selected = item_selected + 1; // select next item
button_down_clicked = 1; // set button to clicked to only perform the action once
if (item_selected >= NUM_ITEMS) { // last item was selected, jump to first menu item
item_selected = 0;
}
}
// draw previous item as icon + label if ((BUTTON_UP_PIN == HIGH) && (button_up_clicked == 1)) { // unclick
u8g2.setFont(u8g_font_7x14); button_up_clicked = 0;
u8g2.drawStr(25, 15, menu_items[item_sel_previous]); }
u8g2.drawBitmap( 4, 2, 16/8, 16, bitmap_icons[item_sel_previous]); if ((BUTTON_DOWN_PIN == HIGH) && (button_down_clicked == 1)) { // unclick
button_down_clicked = 0;
}
// draw selected item as icon + label in bold font
u8g2.setFont(u8g_font_7x14B);
u8g2.drawStr(25, 15+20+2, menu_items[item_selected]);
u8g2.drawBitmap( 4, 24, 16/8, 16, bitmap_icons[item_selected]);
// draw next item as icon + label
u8g2.setFont(u8g_font_7x14);
u8g2.drawStr(25, 15+20+20+2+2, menu_items[item_sel_next]);
u8g2.drawBitmap( 4, 46, 16/8, 16, bitmap_icons[item_sel_next]);
// draw scrollbar background
u8g2.drawBitmap(128-8, 0, 8/8, 64, bitmap_scrollbar_background);
// draw scrollbar handle
u8g2.drawBox(125, 64/NUM_ITEMS * item_selected, 3, 64/NUM_ITEMS);
// draw upir logo
u8g2.drawBitmap(128-16-4, 64-4, 16/8, 4, upir_logo);
}
else if (current_screen == 1) { // SCREENSHOTS SCREEN
u8g2.drawBitmap( 0, 0, 128/8, 64, bitmap_screenshots[item_selected]); // draw screenshot
} }
else if (current_screen == 2) { // QR SCREEN
u8g2.drawBitmap( 0, 0, 128/8, 64, bitmap_qr_codes[item_selected]); // draw qr code screenshot
}
} while ( u8g2.nextPage() ); // required for page drawing mode with u8g library
} if ((BUTTON_SELECT_PIN == LOW) && (button_select_clicked == 0)) { // select button clicked, jump between screens
button_select_clicked = 1; // set button to clicked to only perform the action once
if (current_screen == 0) {current_screen = 1;} // menu items screen --> screenshots screen
else if (current_screen == 1) {current_screen = 2;} // screenshots screen --> qr codes screen
else {current_screen = 0;} // qr codes screen --> menu items screen
}
if ((BUTTON_SELECT_PIN == HIGH) && (button_select_clicked == 1)) { // unclick
button_select_clicked = 0;
}
void MUXSetup() // set correct values for the previous and next items
{ item_sel_previous = item_selected - 1;
pinMode(D3, OUTPUT); // MUX enable if (item_sel_previous < 0) {item_sel_previous = NUM_ITEMS - 1;} // previous item would be below first = make it the last
pinMode(D6, OUTPUT); // MUX address A item_sel_next = item_selected + 1;
pinMode(D7, OUTPUT); // MUX address B if (item_sel_next >= NUM_ITEMS) {item_sel_next = 0;} // next item would be after last = make it the first
pinMode(D9, OUTPUT); // MUX address C
pinMode(D8, OUTPUT); // MUX address D
pinMode(A0, INPUT); // MUX input
}
// Function to parse joystick data to hard values
//If joystick is Up then the value is 1 of var A
//If joystick is Down then the value is 1 of var B
//If joystick is in the middle A and B are 0
hardJoystickValues GUIParser(){
// Define joystick offsets (calibrated resting values) u8g2.firstPage(); // required for page drawing mode for u8g library
const int offsetPWMCH1 = 1090; // Resting value for PWMCH1 (right joystick Y-axis) do {
const int offsetPWMCH2 = 1072; // Resting value for PWMCH2 (right joystick X-axis)
const int offsetPWMCH3 = 1043; // Resting value for PWMCH3 (left joystick X-axis)
const int offsetPWMCH4 = 1476; // Resting value for PWMCH4 (left joystick Y-axis)
// Define deadzone threshold if (current_screen == 0) { // MENU SCREEN
const int deadzone = 120;
// Adjust joystick values by subtracting offsets // selected item background
int adjustedPWMCH1 = JoystickData.PWMCH1 - offsetPWMCH1; u8g2.drawBitmap(0, 22, 128/8, 21, bitmap_item_sel_outline);
int adjustedPWMCH2 = JoystickData.PWMCH2 - offsetPWMCH2;
int adjustedPWMCH3 = JoystickData.PWMCH3 - offsetPWMCH3;
int adjustedPWMCH4 = JoystickData.PWMCH4 - offsetPWMCH4;
// Apply deadzone // draw previous item as icon + label
if (abs(adjustedPWMCH1) < deadzone) adjustedPWMCH1 = 0; //abs to avoid negatives u8g2.setFont(u8g_font_7x14);
if (abs(adjustedPWMCH2) < deadzone) adjustedPWMCH2 = 0; u8g2.drawStr(25, 15, menu_items[item_sel_previous]);
if (abs(adjustedPWMCH3) < deadzone) adjustedPWMCH3 = 0; u8g2.drawBitmap( 4, 2, 16/8, 16, bitmap_icons[item_sel_previous]);
if (abs(adjustedPWMCH4) < deadzone) adjustedPWMCH4 = 0;
// Map joystick values to hard values // draw selected item as icon + label in bold font
int LXU = 0; // Left joystick X axis up u8g2.setFont(u8g_font_7x14B);
int LXD = 0; // Left joystick X axis down u8g2.drawStr(25, 15+20+2, menu_items[item_selected]);
if (adjustedPWMCH1 > 0) { u8g2.drawBitmap( 4, 24, 16/8, 16, bitmap_icons[item_selected]);
LXU = 1; // Joystick is up
} else if (adjustedPWMCH1 < 0) {
LXD = 1; // Joystick is down
}
return {LXU, LXD, 0, 0}; // Return the values as a struct
}
int analogReadMultiPlexer(int addressA, int addressB, int addressC, int addressD, int pin) // draw next item as icon + label
{ u8g2.setFont(u8g_font_7x14);
digitalWrite(D3, LOW); u8g2.drawStr(25, 15+20+20+2+2, menu_items[item_sel_next]);
digitalWrite(D6, addressA); u8g2.drawBitmap( 4, 46, 16/8, 16, bitmap_icons[item_sel_next]);
digitalWrite(D7, addressB);
digitalWrite(D9, addressC);
digitalWrite(D8, addressD);
return analogRead(pin);
}
int mapPot(int normalizedValue) // draw scrollbar background
{ u8g2.drawBitmap(128-8, 0, 8/8, 64, bitmap_scrollbar_background);
return map(normalizedValue, 400, 2500, MINPWMVALUE, MAXPWMVALUE); // map the normalized value to the PWM range
} // draw scrollbar handle
``` u8g2.drawBox(125, 64/NUM_ITEMS * item_selected, 3, 64/NUM_ITEMS);
// draw upir logo
u8g2.drawBitmap(128-16-4, 64-4, 16/8, 4, upir_logo);
}
else if (current_screen == 1) { // SCREENSHOTS SCREEN
u8g2.drawBitmap( 0, 0, 128/8, 64, bitmap_screenshots[item_selected]); // draw screenshot
}
else if (current_screen == 2) { // QR SCREEN
u8g2.drawBitmap( 0, 0, 128/8, 64, bitmap_qr_codes[item_selected]); // draw qr code screenshot
}
} while ( u8g2.nextPage() ); // required for page drawing mode with u8g library
}
void MUXSetup()
{
pinMode(D3, OUTPUT); // MUX enable
pinMode(D6, OUTPUT); // MUX address A
pinMode(D7, OUTPUT); // MUX address B
pinMode(D9, OUTPUT); // MUX address C
pinMode(D8, OUTPUT); // MUX address D
pinMode(A0, INPUT); // MUX input
}
// Function to parse joystick data to hard values
//If joystick is Up then the value is 1 of var A
//If joystick is Down then the value is 1 of var B
//If joystick is in the middle A and B are 0
hardJoystickValues GUIParser(){
// Define joystick offsets (calibrated resting values)
const int offsetPWMCH1 = 1090; // Resting value for PWMCH1 (right joystick Y-axis)
const int offsetPWMCH2 = 1072; // Resting value for PWMCH2 (right joystick X-axis)
const int offsetPWMCH3 = 1043; // Resting value for PWMCH3 (left joystick X-axis)
const int offsetPWMCH4 = 1476; // Resting value for PWMCH4 (left joystick Y-axis)
// Define deadzone threshold
const int deadzone = 120;
// Adjust joystick values by subtracting offsets
int adjustedPWMCH1 = JoystickData.PWMCH1 - offsetPWMCH1;
int adjustedPWMCH2 = JoystickData.PWMCH2 - offsetPWMCH2;
int adjustedPWMCH3 = JoystickData.PWMCH3 - offsetPWMCH3;
int adjustedPWMCH4 = JoystickData.PWMCH4 - offsetPWMCH4;
// Apply deadzone
if (abs(adjustedPWMCH1) < deadzone) adjustedPWMCH1 = 0; //abs to avoid negatives
if (abs(adjustedPWMCH2) < deadzone) adjustedPWMCH2 = 0;
if (abs(adjustedPWMCH3) < deadzone) adjustedPWMCH3 = 0;
if (abs(adjustedPWMCH4) < deadzone) adjustedPWMCH4 = 0;
// Map joystick values to hard values
int LXU = 0; // Left joystick X axis up
int LXD = 0; // Left joystick X axis down
if (adjustedPWMCH1 > 0) {
LXU = 1; // Joystick is up
} else if (adjustedPWMCH1 < 0) {
LXD = 1; // Joystick is down
}
return {LXU, LXD, 0, 0}; // Return the values as a struct
}
int analogReadMultiPlexer(int addressA, int addressB, int addressC, int addressD, int pin)
{
digitalWrite(D3, LOW);
digitalWrite(D6, addressA);
digitalWrite(D7, addressB);
digitalWrite(D9, addressC);
digitalWrite(D8, addressD);
return analogRead(pin);
}
int mapPot(int normalizedValue)
{
return map(normalizedValue, 400, 2500, MINPWMVALUE, MAXPWMVALUE); // map the normalized value to the PWM range
}
```
This is the full code of the screen. The schematic for the pcb can be found in [the final project page](/docs/final_project/final_project.md) This is the full code of the screen. The schematic for the pcb can be found in [the final project page](/docs/final_project/final_project.md)
https://www.tinytronics.nl/en/displays/oled/0.96-inch-oled-display-128*64-pixels-blue-i2c https://www.tinytronics.nl/en/displays/oled/0.96-inch-oled-display-128*64-pixels-blue-i2c