#include "U8glib.h"
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI
// 'digit_0', 16x28px
const unsigned char bitmap_digit_0 [] PROGMEM = {
0x0f, 0xff, 0x1f, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xfc, 0x3f,
0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f,
0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xf8
};
// 'digit_1', 16x28px
const unsigned char bitmap_digit_1 [] PROGMEM = {
0x01, 0xf8, 0x03, 0xf8, 0x07, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8,
0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8,
0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8,
0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8
};
// 'digit_2', 16x28px
const unsigned char bitmap_digit_2 [] PROGMEM = {
0x0f, 0xfe, 0x1f, 0xff, 0x3f, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xfc, 0x3f,
0xfc, 0x3f, 0x00, 0x3f, 0x00, 0x7f, 0x00, 0xff, 0x01, 0xfe, 0x03, 0xfc, 0x0f, 0xf8, 0x1f, 0xf0,
0x3f, 0xe0, 0x7f, 0xc0, 0xff, 0x00, 0xfe, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
// 'digit_3', 16x28px
const unsigned char bitmap_digit_3 [] PROGMEM = {
0x0f, 0xfe, 0x3f, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xf8, 0x3f,
0xf8, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0xfe, 0x00, 0xfc, 0x00, 0xf8, 0x00, 0xff, 0x00, 0xff,
0x00, 0xff, 0x00, 0x3f, 0x00, 0x3f, 0xf8, 0x3f, 0xf8, 0x3f, 0xf8, 0x3f, 0xfc, 0x3f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xf8
};
// 'digit_4', 16x28px
const unsigned char bitmap_digit_4 [] PROGMEM = {
0x00, 0x70, 0x00, 0x78, 0x00, 0xfc, 0x00, 0xfe, 0x01, 0xff, 0x03, 0xff, 0x03, 0xff, 0x07, 0xff,
0x07, 0xff, 0x0f, 0xff, 0x0f, 0xbf, 0x1f, 0xbf, 0x1f, 0x3f, 0x3f, 0x3f, 0x3e, 0x3f, 0x7e, 0x3f,
0x7c, 0x3f, 0xfc, 0x3f, 0xff, 0xff, 0x7f, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x1f, 0xff, 0x00, 0x3f,
0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f
};
// 'digit_5', 16x28px
const unsigned char bitmap_digit_5 [] PROGMEM = {
0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xfc, 0x00, 0xfc, 0x00,
0xfc, 0x00, 0xfc, 0x00, 0xfe, 0x00, 0xff, 0xf0, 0xff, 0xf8, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xff,
0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x7f, 0xff, 0xff,
0xff, 0xff, 0x7f, 0xff, 0x3f, 0xff, 0x1f, 0xff
};
// 'digit_6', 16x28px
const unsigned char bitmap_digit_6 [] PROGMEM = {
0x0f, 0xfe, 0x1f, 0xff, 0x3f, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xfc, 0x3f,
0xfc, 0x3f, 0xfc, 0x00, 0xfc, 0x00, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x7f, 0xff, 0xff,
0xff, 0xfe, 0xff, 0xfc, 0xff, 0xf8, 0xff, 0xf0
};
// 'digit_7', 16x28px
const unsigned char bitmap_digit_7 [] PROGMEM = {
0xff, 0xf0, 0xff, 0xf8, 0xff, 0xfc, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3e, 0xf8, 0x7e,
0xf8, 0x7e, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x01, 0xf8, 0x01, 0xf8, 0x01, 0xf8, 0x03, 0xf0,
0x03, 0xf0, 0x07, 0xf0, 0x07, 0xe0, 0x07, 0xe0, 0x0f, 0xc0, 0x0f, 0xc0, 0x0f, 0xc0, 0x1f, 0x80,
0x1f, 0x80, 0x3f, 0x80, 0x3f, 0x00, 0x3f, 0x00
};
// 'digit_8', 16x28px
const unsigned char bitmap_digit_8 [] PROGMEM = {
0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xfc, 0x3e, 0xfc, 0x3e,
0xfc, 0x3e, 0xfc, 0x3e, 0xfc, 0x3e, 0xfc, 0x3e, 0xff, 0xfc, 0xff, 0xf8, 0x1f, 0xff, 0x7f, 0xff,
0xff, 0xff, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xf8
};
// 'digit_9', 16x28px
const unsigned char bitmap_digit_9 [] PROGMEM = {
0x07, 0xff, 0x1f, 0xff, 0x3f, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xfc, 0x3f,
0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0x3f, 0x00, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xf8
};
// 'Hintergrund', 72x64px
const unsigned char epd_bitmap_Hintergrund [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x08,
0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x00, 0x38, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x16, 0x00,
0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x21, 0x80, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00,
0x40, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x12, 0xf0,
0x00, 0x03, 0xbc, 0x10, 0x00, 0x00, 0x10, 0x12, 0x90, 0x00, 0x04, 0x24, 0x08, 0x00, 0x00, 0x20,
0x1e, 0x90, 0x00, 0x07, 0x24, 0x04, 0x00, 0x00, 0x40, 0x02, 0x90, 0x00, 0x04, 0xa4, 0x04, 0x00,
0x00, 0x40, 0x02, 0x90, 0x00, 0x04, 0xa4, 0x02, 0x00, 0x00, 0x80, 0x02, 0xf0, 0x00, 0x03, 0x3c,
0x01, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x01, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x73, 0xc0, 0x00, 0x00, 0x00, 0x01, 0x9e, 0x08,
0x10, 0x0a, 0x40, 0x00, 0x00, 0x00, 0x02, 0x52, 0x08, 0x1f, 0x12, 0x40, 0x00, 0x00, 0x00, 0x01,
0x92, 0xf8, 0x10, 0x22, 0x40, 0x00, 0x00, 0x00, 0x02, 0x52, 0x08, 0x10, 0x42, 0x40, 0x00, 0x00,
0x00, 0x02, 0x52, 0x08, 0x10, 0x7b, 0xc0, 0x00, 0x00, 0x00, 0x01, 0x9e, 0x08, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00,
0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x04, 0x80, 0x00, 0x00, 0x28, 0x00, 0x00, 0x02, 0x40,
0x05, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, 0x40, 0x02, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00,
0x00, 0x80, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x3c, 0x02, 0x00,
0x82, 0xf7, 0x81, 0x00, 0x00, 0x80, 0x24, 0x05, 0x76, 0x42, 0x94, 0x81, 0x00, 0x00, 0x40, 0x24,
0x09, 0x45, 0x22, 0x94, 0x82, 0x00, 0x00, 0x40, 0x24, 0x11, 0x67, 0x12, 0x94, 0x84, 0x00, 0x00,
0x20, 0x24, 0x09, 0x45, 0x22, 0x94, 0x88, 0x00, 0x00, 0x10, 0x3c, 0x05, 0x45, 0x42, 0xf7, 0x90,
0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x04, 0x10, 0x01, 0x01, 0x00,
0x10, 0x40, 0x00, 0x00, 0x02, 0x20, 0x00, 0x82, 0x00, 0x08, 0x80, 0x00, 0x00, 0x01, 0x40, 0x00,
0x44, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// 'KMH', 32x10px
const unsigned char epd_bitmap_KMH [] PROGMEM = {
0xc6, 0xc1, 0x82, 0x63, 0xcc, 0xe3, 0x86, 0x63, 0xd8, 0xf7, 0x84, 0x63, 0xf0, 0xdd, 0x84, 0x7f,
0xe0, 0xc9, 0x8c, 0x7f, 0xf0, 0xc1, 0x88, 0x63, 0xd0, 0xc1, 0x98, 0x63, 0xd8, 0xc1, 0x90, 0x63,
0xcc, 0xc1, 0xb0, 0x63, 0xc6, 0xc1, 0xa0, 0x63
};
// 'Mitte_fill', 8x8px
const unsigned char epd_bitmap_Mitte_fill [] PROGMEM = {
0x00, 0x3c, 0x7e, 0x7e, 0x7e, 0x7e, 0x3c, 0x00
};
// 'Mitte_rand', 8x8px
const unsigned char epd_bitmap_Mitte_rand [] PROGMEM = {
0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00
};
// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 800)
const int bitmap_allArray_LEN = 10;
const unsigned char* bitmap_allArray[10] = {
bitmap_digit_0,
bitmap_digit_1,
bitmap_digit_2,
bitmap_digit_3,
bitmap_digit_4,
bitmap_digit_5,
bitmap_digit_6,
bitmap_digit_7,
bitmap_digit_8,
bitmap_digit_9
};
int speed = 0;
char speed_string[10];
int speed_string_length; // length of the speed_string
int speed_string_start_pos; // start x position for the big numbers - calculated based on the number of digits
int needle_angle_deg = 45; // angle of the needle in degrees, based on potentiometer value
int needle_start_x; // needle start point, x position
int needle_start_y; // needle start point, y position
int needle_end_x; // needle end point, x position
int needle_end_y; // needle end point, y position
int needle_center_x = 35; // needle center position, x position
int needle_center_y = 34; // needle center position, y position
int needle_radius_big = 30; // lenght of needle
int needle_radius_small = 10; // lenght of "tail" of the needle
int needle_offset_x; // second line offset x
int needle_offset_y; // second line offset y
void setup() {
u8g.setFont(u8g_font_tpssb);
u8g.setColorIndex(1);
pinMode(A0, INPUT);
}
void loop() {
speed = map(analogRead(A0), 0, 1023, 0, 100);
itoa (speed,speed_string,10);
speed_string_length = strlen(speed_string);
speed_string_start_pos = 97 - speed_string_length * 8;
needle_angle_deg = map(speed, 0, 100, 33, 282+45); // calculate the angle in degrees based on the speed value, between 45-315
needle_start_x = needle_radius_big * -sin(radians(needle_angle_deg)) + needle_center_x; // calculate needle start x position
needle_start_y = needle_radius_big * cos(radians(needle_angle_deg)) + needle_center_y; // calculate needle start y position
needle_end_x = needle_radius_small * -sin(radians(needle_angle_deg + 180)) + needle_center_x; // calculate needle end x position
needle_end_y = needle_radius_small * cos(radians(needle_angle_deg + 180)) + needle_center_y; // calculate needle end y position
// calculate offset for the second line for the needle, based on the needle slope
if ((needle_angle_deg > 32 && needle_angle_deg < 135) || (needle_angle_deg > 225 && needle_angle_deg < 327)) {
// needle is more horizontal, offset the second line by y
needle_offset_x = 0;
needle_offset_y = 1;
} else {
// needle is more vertical, offset the second line by x
needle_offset_x = 1;
needle_offset_y = 0;
}
u8g.firstPage();
do{
for (int i = 0; i < speed_string_length; i++) { // loop for every speed_string character
// draw the big digit
// subtract value 45 from the character value, since the ASCII value of digit "0" is 48
u8g.drawBitmapP(speed_string_start_pos + 18 * i, 4, 16/8, 28, bitmap_allArray[speed_string[i] - 48]);
}
u8g.drawBitmapP(0, 0, 72/8, 64, epd_bitmap_Hintergrund);
u8g.drawLine(needle_start_x, needle_start_y, needle_end_x, needle_end_y); // draw first line for the needle
u8g.drawLine(needle_start_x+needle_offset_x, needle_start_y+needle_offset_y, needle_end_x+needle_offset_x, needle_end_y+needle_offset_y); // draw second line for the needle
u8g.setColorIndex(0);
u8g.drawBitmapP(31, 31, 8/8, 8, epd_bitmap_Mitte_fill);
u8g.setColorIndex(1);
u8g.drawBitmapP(31, 31, 8/8, 8, epd_bitmap_Mitte_rand);
u8g.drawBitmapP(84, 33, 32/8, 10, epd_bitmap_KMH);
} while (u8g.nextPage());
}