// simple project using Arduino UNO and 128x64 OLED Display for parking sensor
// created by upir, 2022
// youtube channel: https://www.youtube.com/upir_upir
// youtube video: https://youtu.be/sEWw087KOj0
// youtube full video: https://youtu.be/gg08H-6Z1Lo
// Github: https://github.com/upiir/arduino_parking_sensor
// u8g fonts (fonts available for u8g library): https://nodemcu-build.com/u8g-fonts.php
// u8g documentation: https://github.com/olikraus/u8glib/wiki/userreference
// Wokwi starting project: https://wokwi.com/arduino/projects/300867986768527882
// Wokwi starting project distance sensor: https://wokwi.com/projects/304444938977804866
// Photopea (online Photoshop-like tool): https://www.photopea.com/
// image2cpp (convert images into C code): https://javl.github.io/image2cpp/
// useful links:
// OLED Display: https://s.click.aliexpress.com/e/_AWSVnt
// 128x64 SSD1306 OLED Display: https://s.click.aliexpress.com/e/_DCKdvnh
// Transparent OLED display: https://s.click.aliexpress.com/e/_Dns6eLz
// u8g documentation: https://github.com/olikraus/u8glib/wiki/userreference
// Arduino UNO: https://s.click.aliexpress.com/e/_AXDw1h
// Arduino UNO MINI: https://store.arduino.cc/products/uno-mini-le
// Big OLED Display: https://s.click.aliexpress.com/e/_ADL0T9
// Arduino breadboard prototyping shield: https://s.click.aliexpress.com/e/_ApbCwx
// Related videos:
// Turbo pressure gauge with Arduino and OLED display - https://youtu.be/JXmw1xOlBdk
// Arduino Car Cluster with OLED Display - https://youtu.be/El5SJelwV_0
// Knob over OLED Display - https://youtu.be/SmbcNx7tbX8
// Arduino + OLED = 3D ? - https://youtu.be/kBAcaA7NAlA
// Arduino OLED Gauge - https://youtu.be/xI6dXTA02UQ
#include "U8glib.h"
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI
// 'car_image', 56x15px
const unsigned char bitmap_car_image [] PROGMEM = {
0xc0, 0x40, 0x00, 0x00, 0x00, 0x02, 0x03, 0xc0, 0x8f, 0xff, 0xff, 0xff, 0xf1, 0x03, 0xe0, 0x70,
0x00, 0x00, 0x00, 0x0e, 0x07, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xc0, 0xff, 0x00, 0x00,
0x00, 0xff, 0x03, 0xc0, 0x00, 0x05, 0x75, 0xc0, 0x00, 0x03, 0x47, 0xf8, 0x05, 0x51, 0x40, 0x1f,
0xe2, 0x47, 0xfc, 0x05, 0x65, 0x80, 0x3f, 0xe2, 0x40, 0x78, 0x06, 0x45, 0x40, 0x1e, 0x02, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x01, 0xff, 0xff, 0xff, 0x80, 0x78, 0x07, 0xe2, 0x00,
0x00, 0x00, 0x47, 0xe0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xbf, 0xff, 0xff, 0xff,
0xfd, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00
};
// 'sensor_01_a_off', 32x14px
const unsigned char bitmap_sensor_01_a_off [] PROGMEM = {
0x00, 0x40, 0x00, 0x00, 0x02, 0xa8, 0x00, 0x00, 0x05, 0x55, 0x00, 0x00, 0x02, 0xaa, 0xa0, 0x00,
0x05, 0x55, 0x54, 0x00, 0x0a, 0xaa, 0xaa, 0xa0, 0x15, 0x55, 0x55, 0x50, 0x0a, 0xaa, 0xaa, 0xa0,
0x01, 0x55, 0x55, 0x40, 0x00, 0x2a, 0xaa, 0xa0, 0x00, 0x15, 0x55, 0x40, 0x00, 0x02, 0xaa, 0xa0,
0x00, 0x00, 0x15, 0x40, 0x00, 0x00, 0x02, 0xa0
};
// 'sensor_01_a_on', 32x14px
const unsigned char bitmap_sensor_01_a_on [] PROGMEM = {
0x00, 0xc0, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x07, 0xff, 0xe0, 0x00,
0x0f, 0xff, 0xfe, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xe0,
0x03, 0xff, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0xe0, 0x00, 0x1f, 0xff, 0xe0, 0x00, 0x03, 0xff, 0xe0,
0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x03, 0xe0
};
// 'sensor_01_b_off', 32x16px
const unsigned char bitmap_sensor_01_b_off [] PROGMEM = {
0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x00, 0x00, 0x05, 0x54, 0x00, 0x00,
0x0a, 0xaa, 0x80, 0x00, 0x15, 0x55, 0x50, 0x00, 0x0a, 0xaa, 0xaa, 0x80, 0x15, 0x55, 0x55, 0x50,
0x0a, 0xaa, 0xaa, 0xa8, 0x05, 0x55, 0x55, 0x50, 0x00, 0xaa, 0xaa, 0xa8, 0x00, 0x15, 0x55, 0x50,
0x00, 0x02, 0xaa, 0xa0, 0x00, 0x00, 0x55, 0x50, 0x00, 0x00, 0x0a, 0xa0, 0x00, 0x00, 0x00, 0x50
};
// 'sensor_01_b_on', 32x16px
const unsigned char bitmap_sensor_01_b_on [] PROGMEM = {
0x02, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00,
0x0f, 0xff, 0x80, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0x80, 0x3f, 0xff, 0xff, 0xf8,
0x1f, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xf8,
0x00, 0x07, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0xf0
};
// 'sensor_01_c_off', 32x17px
const unsigned char bitmap_sensor_01_c_off [] PROGMEM = {
0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x00, 0x00, 0x15, 0x50, 0x00, 0x00,
0x2a, 0xaa, 0x00, 0x00, 0x15, 0x55, 0x40, 0x00, 0x2a, 0xaa, 0xaa, 0x00, 0x55, 0x55, 0x55, 0x40,
0x2a, 0xaa, 0xaa, 0xaa, 0x15, 0x55, 0x55, 0x54, 0x02, 0xaa, 0xaa, 0xa8, 0x00, 0x55, 0x55, 0x54,
0x00, 0x0a, 0xaa, 0xa8, 0x00, 0x01, 0x55, 0x54, 0x00, 0x00, 0x2a, 0xa8, 0x00, 0x00, 0x05, 0x54,
0x00, 0x00, 0x00, 0x28
};
// 'sensor_01_c_on', 32x17px
const unsigned char bitmap_sensor_01_c_on [] PROGMEM = {
0x08, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00,
0x3f, 0xff, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0xfe, 0x00, 0x7f, 0xff, 0xff, 0xe0,
0x7f, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xfe, 0x03, 0xff, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xfc,
0x00, 0x1f, 0xff, 0xfc, 0x00, 0x03, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x07, 0xfc,
0x00, 0x00, 0x00, 0x3c
};
// 'sensor_01_d_off', 32x18px
const unsigned char bitmap_sensor_01_d_off [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x00, 0x00,
0x55, 0x50, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x50, 0x00, 0xaa, 0xaa, 0xaa, 0x00,
0x55, 0x55, 0x55, 0x50, 0x2a, 0xaa, 0xaa, 0xaa, 0x05, 0x55, 0x55, 0x54, 0x02, 0xaa, 0xaa, 0xaa,
0x00, 0x55, 0x55, 0x54, 0x00, 0x0a, 0xaa, 0xaa, 0x00, 0x01, 0x55, 0x54, 0x00, 0x00, 0x2a, 0xa8,
0x00, 0x00, 0x01, 0x54, 0x00, 0x00, 0x00, 0x08
};
// 'sensor_02_a_off', 32x9px
const unsigned char bitmap_sensor_02_a_off [] PROGMEM = {
0x05, 0x55, 0x55, 0x40, 0x0a, 0xaa, 0xaa, 0xa0, 0x05, 0x55, 0x55, 0x40, 0x0a, 0xaa, 0xaa, 0xa0,
0x05, 0x55, 0x55, 0x40, 0x0a, 0xaa, 0xaa, 0xa0, 0x05, 0x55, 0x55, 0x40, 0x0a, 0xaa, 0xaa, 0xa0,
0x15, 0x55, 0x55, 0x50
};
// 'sensor_01_d_on', 32x18px
const unsigned char bitmap_sensor_01_d_on [] PROGMEM = {
0x20, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00,
0xff, 0xf8, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x00, 0xff, 0xff, 0xfe, 0x00,
0x7f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xfe, 0x03, 0xff, 0xff, 0xfe,
0x00, 0x7f, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xfe, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xfc,
0x00, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x1c
};
// 'sensor_02_a_on', 32x9px
const unsigned char bitmap_sensor_02_a_on [] PROGMEM = {
0x07, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xe0,
0x0f, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xe0,
0x1f, 0xff, 0xff, 0xf0
};
// 'sensor_02_b_off', 32x9px
const unsigned char bitmap_sensor_02_b_off [] PROGMEM = {
0x15, 0x55, 0x55, 0x50, 0x0a, 0xaa, 0xaa, 0xa0, 0x15, 0x55, 0x55, 0x50, 0x0a, 0xaa, 0xaa, 0xa0,
0x15, 0x55, 0x55, 0x50, 0x2a, 0xaa, 0xaa, 0xa8, 0x15, 0x55, 0x55, 0x50, 0x2a, 0xaa, 0xaa, 0xa8,
0x05, 0x55, 0x55, 0x40
};
// 'sensor_02_b_on', 32x9px
const unsigned char bitmap_sensor_02_b_on [] PROGMEM = {
0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0,
0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8,
0x0f, 0xff, 0xff, 0xe0
};
// 'sensor_02_c_off', 32x10px
const unsigned char bitmap_sensor_02_c_off [] PROGMEM = {
0x10, 0x00, 0x00, 0x04, 0x0a, 0xaa, 0xaa, 0xa8, 0x15, 0x55, 0x55, 0x54, 0x2a, 0xaa, 0xaa, 0xaa,
0x15, 0x55, 0x55, 0x54, 0x2a, 0xaa, 0xaa, 0xaa, 0x15, 0x55, 0x55, 0x54, 0x2a, 0xaa, 0xaa, 0xaa,
0x15, 0x55, 0x55, 0x54, 0x0a, 0xaa, 0xaa, 0xa8
};
// 'sensor_02_c_on', 32x10px
const unsigned char bitmap_sensor_02_c_on [] PROGMEM = {
0x18, 0x00, 0x00, 0x0c, 0x1f, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xfe,
0x3f, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xfe,
0x3f, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xf8
};
// 'sensor_02_d_off', 40x10px
const unsigned char bitmap_sensor_02_d_off [] PROGMEM = {
0x02, 0x80, 0x00, 0x00, 0x28, 0x01, 0x55, 0x55, 0x55, 0x50, 0x02, 0xaa, 0xaa, 0xaa, 0xa8, 0x01,
0x55, 0x55, 0x55, 0x50, 0x02, 0xaa, 0xaa, 0xaa, 0xa8, 0x05, 0x55, 0x55, 0x55, 0x54, 0x02, 0xaa,
0xaa, 0xaa, 0xa8, 0x05, 0x55, 0x55, 0x55, 0x54, 0x02, 0xaa, 0xaa, 0xaa, 0xa8, 0x00, 0x55, 0x55,
0x55, 0x40
};
// 'sensor_02_d_on', 40x10px
const unsigned char bitmap_sensor_02_d_on [] PROGMEM = {
0x03, 0x80, 0x00, 0x00, 0x38, 0x03, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xff, 0xf8, 0x03,
0xff, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xff, 0xfc, 0x07, 0xff,
0xff, 0xff, 0xfc, 0x07, 0xff, 0xff, 0xff, 0xfc, 0x07, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xff, 0xff,
0xff, 0xe0
};
// 'sensor_03_a_off', 32x14px
const unsigned char bitmap_sensor_03_a_off [] PROGMEM = {
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x00, 0x01, 0x55, 0x40, 0x00, 0x0a, 0xaa, 0x80,
0x00, 0x55, 0x55, 0x40, 0x0a, 0xaa, 0xaa, 0xa0, 0x15, 0x55, 0x55, 0x50, 0x0a, 0xaa, 0xaa, 0xa0,
0x05, 0x55, 0x55, 0x00, 0x0a, 0xaa, 0xa8, 0x00, 0x05, 0x55, 0x50, 0x00, 0x0a, 0xaa, 0x80, 0x00,
0x05, 0x50, 0x00, 0x00, 0x0a, 0x80, 0x00, 0x00
};
// 'sensor_03_b_on', 32x16px
const unsigned char bitmap_sensor_03_b_on [] PROGMEM = {
0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x3f, 0xf0,
0x00, 0x01, 0xff, 0xf0, 0x00, 0x1f, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xfc,
0x1f, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xfc, 0x00,
0x0f, 0xff, 0xe0, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
};
// 'sensor_03_a_on', 32x14px
const unsigned char bitmap_sensor_03_a_on [] PROGMEM = {
0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x01, 0xff, 0xc0, 0x00, 0x0f, 0xff, 0xc0,
0x00, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xe0,
0x0f, 0xff, 0xff, 0x80, 0x0f, 0xff, 0xfc, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0x80, 0x00,
0x0f, 0xf8, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00
};
// 'sensor_03_b_off', 32x16px
const unsigned char bitmap_sensor_03_b_off [] PROGMEM = {
0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x05, 0x40, 0x00, 0x00, 0x2a, 0xa0,
0x00, 0x01, 0x55, 0x50, 0x00, 0x0a, 0xaa, 0xa8, 0x01, 0x55, 0x55, 0x50, 0x0a, 0xaa, 0xaa, 0xa8,
0x15, 0x55, 0x55, 0x50, 0x0a, 0xaa, 0xaa, 0xa0, 0x15, 0x55, 0x55, 0x00, 0x0a, 0xaa, 0xa8, 0x00,
0x05, 0x55, 0x40, 0x00, 0x0a, 0xaa, 0x00, 0x00, 0x05, 0x50, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00
};
// 'sensor_03_c_off', 32x17px
const unsigned char bitmap_sensor_03_c_off [] PROGMEM = {
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x0a, 0xa8,
0x00, 0x00, 0x55, 0x54, 0x00, 0x02, 0xaa, 0xa8, 0x00, 0x55, 0x55, 0x54, 0x02, 0xaa, 0xaa, 0xaa,
0x55, 0x55, 0x55, 0x54, 0x2a, 0xaa, 0xaa, 0xa8, 0x15, 0x55, 0x55, 0x40, 0x2a, 0xaa, 0xaa, 0x00,
0x15, 0x55, 0x50, 0x00, 0x2a, 0xaa, 0x80, 0x00, 0x15, 0x54, 0x00, 0x00, 0x2a, 0xa0, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00
};
// 'sensor_03_d_on', 32x18px
const unsigned char bitmap_sensor_03_d_on [] PROGMEM = {
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x07, 0xfc,
0x00, 0x00, 0x3f, 0xfe, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xfe, 0x00, 0xff, 0xff, 0xfe,
0x1f, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xf0, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x00,
0x7f, 0x80, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00
};
// 'sensor_03_d_off', 32x18px
const unsigned char bitmap_sensor_03_d_off [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x01, 0x54, 0x00, 0x00, 0x02, 0xa8,
0x00, 0x00, 0x15, 0x54, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x15, 0x55, 0x54, 0x00, 0xaa, 0xaa, 0xaa,
0x15, 0x55, 0x55, 0x54, 0xaa, 0xaa, 0xaa, 0xa8, 0x55, 0x55, 0x55, 0x40, 0xaa, 0xaa, 0xaa, 0x80,
0x55, 0x55, 0x54, 0x00, 0xaa, 0xaa, 0xa0, 0x00, 0x55, 0x55, 0x00, 0x00, 0x2a, 0xa8, 0x00, 0x00,
0x55, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
};
// 'sensor_03_c_on', 32x17px
const unsigned char bitmap_sensor_03_c_on [] PROGMEM = {
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x1f, 0xf8,
0x00, 0x00, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0xfe, 0x07, 0xff, 0xff, 0xfe,
0x7f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xff, 0x00,
0x3f, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xc0, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00,
0x3c, 0x00, 0x00, 0x00
};
// 'sound_on', 24x10px
const unsigned char bitmap_sound_on [] PROGMEM = {
0x03, 0xc0, 0x0f, 0x02, 0x0c, 0x01, 0x02, 0x1c, 0x11, 0x02, 0x3c, 0x49, 0x00, 0x7d, 0x28, 0x00,
0x7d, 0x28, 0x02, 0x3c, 0x49, 0x02, 0x1c, 0x11, 0x02, 0x0c, 0x01, 0x03, 0xc0, 0x0f
};
// 'unit_cm', 24x10px
const unsigned char bitmap_unit_cm [] PROGMEM = {
0xf0, 0x03, 0xc0, 0x80, 0x00, 0x40, 0xbe, 0xff, 0x40, 0xb6, 0xdb, 0x40, 0x30, 0xdb, 0x00, 0x30,
0xdb, 0x00, 0xb6, 0xdb, 0x40, 0xbe, 0xdb, 0x40, 0x80, 0x00, 0x40, 0xf0, 0x03, 0xc0
};
/*
Fontname: gamer_digits
Copyright: Created with Fony 1.4.7
Capital A Height: 0, '1' Height: 6
Calculated Max Values w= 5 h= 6 x= 1 y= 0 dx= 6 dy= 0 ascent= 0 len= 6
Font Bounding box w= 9 h= 5 x= 0 y=-6
Calculated Min Values x= 0 y=-6 dx= 0 dy= 0
Pure Font ascent = 6 descent= 0
X Font ascent = 6 descent= 0
Max Font ascent = 0 descent=-6
*/
const u8g_fntpgm_uint8_t gamer_digits[137] U8G_FONT_SECTION("gamer_digits") = {
0,9,5,0,250,6,0,0,0,0,48,57,0,0,250,6,
0,5,6,6,6,0,250,248,216,216,216,216,248,4,6,6,
6,1,250,224,96,96,96,96,240,5,6,6,6,0,250,248,
24,120,192,192,248,5,6,6,6,0,250,248,24,248,24,216,
248,5,6,6,6,0,250,56,120,216,248,24,24,5,6,6,
6,0,250,248,192,248,24,24,248,5,6,6,6,0,250,248,
192,248,216,216,248,5,6,6,6,0,250,248,24,24,24,24,
24,5,6,6,6,0,250,248,216,248,216,216,248,5,6,6,
6,0,250,248,216,216,248,24,248};
// set the correct pins for the distance sensors, we can (probably) use any digital pins
#define sensor_01_ECHO_PIN 6
#define sensor_01_TRIG_PIN 7
#define sensor_02_ECHO_PIN 4
#define sensor_02_TRIG_PIN 5
#define sensor_03_ECHO_PIN 2
#define sensor_03_TRIG_PIN 3
// number of sensors - note that adding a new sensor is not as simple as changing the number, as the image drawing is hardcoded
#define NUMBER_OF_SENSORS 3
struct sensor_data { // structure for the sensor data
int echo_pin; // ECHO pin for the ultrasonic distance sensor
int trig_pin; // TRIG pin for the ultrasonic distance sensor
int measured_distance_cm; // measured distance in CM
int label_xpos; // x position of the distance label
int label_ypos; // y position of the distance label
int label_width; // calculated width of the distance string
int label_startpos_x; // start X position for the label
int label_startpos_y; // start Y position for the label
int label_endpos_x; // end X position for the label
int label_endpos_y; // end Y position for the label
};
char buffer[10]; // helper C-style array of characters to store integers converted to strings
struct sensor_data sensor[NUMBER_OF_SENSORS]; // we have 3 sensors for now
int min_dist = 2; // minimum distance to display in cm, this is also the minimum measurable distance for the used sensor
int max_dist = 100; // maximum distance to display in cm with the tile images, maximum measurable distance is 400cm = 4m
int dist_step_01; // distance for the first tile (there are 4 tiles for each sensor)
int dist_step_02; // distance for the 2nd tile
int dist_step_03; // distance for the 3rd tile
int dist_step_04; // distance for the 4th tile
void setup() {
// calculate individual steps for the 4 tiles
dist_step_01 = min_dist + round((max_dist - min_dist) / 4.0 * 1.0);
dist_step_02 = min_dist + round((max_dist - min_dist) / 4.0 * 2.0);
dist_step_03 = min_dist + round((max_dist - min_dist) / 4.0 * 3.0);
dist_step_04 = min_dist + round((max_dist - min_dist) / 4.0 * 4.0);
// initialize pins for sensors
sensor[0].echo_pin = sensor_01_ECHO_PIN;
sensor[0].trig_pin = sensor_01_TRIG_PIN;
sensor[1].echo_pin = sensor_02_ECHO_PIN;
sensor[1].trig_pin = sensor_02_TRIG_PIN;
sensor[2].echo_pin = sensor_03_ECHO_PIN;
sensor[2].trig_pin = sensor_03_TRIG_PIN;
// set pins to outputs and inputs - trigger is output, echo is input
pinMode(sensor[0].trig_pin, OUTPUT);
pinMode(sensor[0].echo_pin, INPUT);
pinMode(sensor[1].trig_pin, OUTPUT);
pinMode(sensor[1].echo_pin, INPUT);
pinMode(sensor[2].trig_pin, OUTPUT);
pinMode(sensor[2].echo_pin, INPUT);
// initialize label position data
// those are manualy defined in the Photoshop/Photopea file, since it´s just easier to do it that way instead of guessing the numbers
sensor[0].label_startpos_x = 41;
sensor[0].label_startpos_y = 20;
sensor[0].label_endpos_x = 30;
sensor[0].label_endpos_y = 58;
sensor[1].label_startpos_x = 63;
sensor[1].label_startpos_y = 23;
sensor[1].label_endpos_x = 63;
sensor[1].label_endpos_y = 60;
sensor[2].label_startpos_x = 85;
sensor[2].label_startpos_y = 20;
sensor[2].label_endpos_x = 97;
sensor[2].label_endpos_y = 57;
u8g.setFont(gamer_digits); // gamer digits font - manually generated, only includes digits
u8g.setColorIndex(1); // white color
Serial.begin(115200); // debug only
}
void loop() {
for (int i=0; i<NUMBER_OF_SENSORS; i++) { // for each sensor
// MEASURE DISTANCES
// trigger the trigger pin for at least 10 microseconds
digitalWrite(sensor[i].trig_pin, HIGH);
delayMicroseconds(10);
digitalWrite(sensor[i].trig_pin, LOW);
// Read the result:
sensor[i].measured_distance_cm = pulseIn(sensor[i].echo_pin, HIGH); // pulseIn command will measure the time for the pulse on a defined pin
sensor[i].measured_distance_cm = round(sensor[i].measured_distance_cm * 0.0343 / 2.0); // speed of sound = 343m/s, has to travel back and forth, that´s why we divide it by 2
//Serial.print("Sensor ");
//Serial.print(i);
//Serial.print(" ");
//Serial.println(sensor[i].measured_distance_cm);
// calculate string width
itoa(sensor[i].measured_distance_cm, buffer, 10); // convert integer to C-style string
sensor[i].label_width = u8g.getStrWidth(buffer);
// calculate label positions
sensor[i].label_xpos = map(constrain(sensor[i].measured_distance_cm, min_dist, max_dist), min_dist, max_dist, sensor[i].label_startpos_x, sensor[i].label_endpos_x);
sensor[i].label_ypos = map(constrain(sensor[i].measured_distance_cm, min_dist, max_dist), min_dist, max_dist, sensor[i].label_startpos_y, sensor[i].label_endpos_y);
}
//delay(500);
u8g.firstPage();
do {
u8g.drawBitmapP( 36, 0, 56/8, 15, bitmap_car_image); // car image on top of the display
u8g.drawBitmapP( 104, 0, 24/8, 10, bitmap_sound_on); // sound on indicator - not doing anything for now
u8g.drawBitmapP( 0, 0, 24/8, 10, bitmap_unit_cm); // cm unit indicator - not doing anything for now
// individual pieces of the distance measurement in the 3*4 grid
u8g.drawBitmapP( 24, 17, 32/8, 14, sensor[0].measured_distance_cm > dist_step_01 ? bitmap_sensor_01_a_on : bitmap_sensor_01_a_off);
u8g.drawBitmapP( 21, 25, 32/8, 16, sensor[0].measured_distance_cm > dist_step_02 ? bitmap_sensor_01_b_on : bitmap_sensor_01_b_off);
u8g.drawBitmapP( 18, 34, 32/8, 17, sensor[0].measured_distance_cm > dist_step_03 ? bitmap_sensor_01_c_on : bitmap_sensor_01_c_off);
u8g.drawBitmapP( 16, 43, 32/8, 18, sensor[0].measured_distance_cm > dist_step_04 ? bitmap_sensor_01_d_on : bitmap_sensor_01_d_off);
u8g.drawBitmapP( 48, 23, 32/8, 9, sensor[1].measured_distance_cm > dist_step_01 ? bitmap_sensor_02_a_on : bitmap_sensor_02_a_off);
u8g.drawBitmapP( 48, 33, 32/8, 9, sensor[1].measured_distance_cm > dist_step_02 ? bitmap_sensor_02_b_on : bitmap_sensor_02_b_off);
u8g.drawBitmapP( 47, 42, 32/8, 10, sensor[1].measured_distance_cm > dist_step_03 ? bitmap_sensor_02_c_on : bitmap_sensor_02_c_off);
u8g.drawBitmapP( 42, 52, 40/8, 10, sensor[1].measured_distance_cm > dist_step_04 ? bitmap_sensor_02_d_on : bitmap_sensor_02_d_off);
u8g.drawBitmapP( 72, 17, 32/8, 14, sensor[2].measured_distance_cm > dist_step_01 ? bitmap_sensor_03_a_on : bitmap_sensor_03_a_off);
u8g.drawBitmapP( 74, 25, 32/8, 16, sensor[2].measured_distance_cm > dist_step_02 ? bitmap_sensor_03_b_on : bitmap_sensor_03_b_off);
u8g.drawBitmapP( 77, 34, 32/8, 17, sensor[2].measured_distance_cm > dist_step_03 ? bitmap_sensor_03_c_on : bitmap_sensor_03_c_off);
u8g.drawBitmapP( 80, 43, 32/8, 18, sensor[2].measured_distance_cm > dist_step_04 ? bitmap_sensor_03_d_on : bitmap_sensor_03_d_off);
for (int i=0; i<NUMBER_OF_SENSORS; i++) { // for all the sensors
u8g.setColorIndex(0); // black color
// draw box below the label
u8g.drawBox((sensor[i].label_xpos - sensor[i].label_width / 2) - 1 ,sensor[i].label_ypos - 4,sensor[i].label_width + 2, 8);
itoa(sensor[i].measured_distance_cm, buffer, 10); // convert integer to C-style string
u8g.setColorIndex(1); // white color
// draw the distance label
u8g.drawStr(sensor[i].label_xpos - sensor[i].label_width / 2, sensor[i].label_ypos - 3, buffer); // draw the label
}
} while ( u8g.nextPage() );
}