Да ладно, GPS сам не быстро выдаёт скоростя. Зато видно будет отлично. Реально спидометр на лодке нужен немного меньше, чем козе баян или зайцу стоп-сигнал. Но прикольно.
Ещё можно по прямому назначению - как электронную книгу сделать, страница 15 кб всего. Хотя для детских книжек цветной экран лучше.
у меня и так две штуки есть, куда их столько… Почему я и подумал о спидометре - на солнце книгу видно отлично, а планшет плохо. На часах спидометр неплохо видно, но блин через время эпловачи сбрасывают программу спидометрии… а руки-то заняты, румпель держать надо.
А так спидометр сделать это в основном отображением заняться: надо бы конечно ещё и графически изобразить спидометр, будет ваще козырно. GPSов у меня штуки 3 лежат, начать да кончить.
Это просто фоновая картинка, а вот анимация стрелки интересна.
Предполагаю сначала просто большие цифры сделать, а потом добавить такую заполняемую цветом дугу и прочие мелочи, типа число спутников, расстояние, путь и тп.
Питание акк 4.2в - стаб 3.3в; включается полевиком, откл через N минут при скорости около нуля. Перед отключением выводить типа путь, макс скорость.
Гармин, например, использует т.н. трансрефлективные дешевые дисплеи, они, во-первых цветные, во вторых - чем ярче солнце - тем лучше видно ![]()
Из тех транс-ЖК что я видел, эл. бумага ярче на солнце. Ну и гармин непонятно что тогда рукож-ть )) неспортивно.
И да, может где-то их можно куплять? Можно тогда посмотреть. Отдельно дисплеи в смысле.
От того места к которому едешь.
похоже они все были трезвенниками
Ну, да. Сначала западаешь на содержание мысли, а уже потом смотришь кто сказал ![]()
Решил повозиться с 4 цветами, расширить возможности исходного ПО. Пока добрался до рисования пикселей заданным цветом по координатам. Сделал, но не понимаю почему так, а не по другому.
#include <SPI.h>
#include "epd4in2_V2.h"
#include "imagedata.h"
unsigned char bufer[30000];// массив для данных цвета пикселей экрана
Epd epd;
void setup() {
/////////////////////
epd.Init_4Gray();
/*
Dis_Cvet(3);Buf_Ris();
delay(2000);
Dis_Cvet(2);Buf_Ris();
delay(2000);
Dis_Cvet(1);Buf_Ris();
delay(2000);
Dis_Cvet(0);Buf_Ris();
delay(2000);
*/
//Dis_Cvet(3);Pixel(0,0,0);Pixel(399,0,0);Pixel(0,299,0);Pixel(399,299,0);
for(int i=0;i<400;i++){
for(int j=0;j<300;j++){
if(i%60<30&&j%60<30){Pixel(i,j,0);}
if(i%60<60&&i%60>=30&&j%60<30){Pixel(i,j,2);}
if(i%60<60&&i%60>=30&&j%60>=30&&j%60<60){Pixel(i,j,1);}
if(i%60<30&&j%60>=30&&j%60<60){Pixel(i,j,3);}
}
}
Buf_Ris();
// epd.Clear();
////////////////
epd.Sleep();
}
void loop() {
// put your main code here, to run repeatedly:
}
/////////////////////
void Buf_Ris(){//
epd.Buf_4GrayDisplay(bufer,0,0,400,300);// самописная функция на основе штатной epd.Set_4GrayDisplay(gImage_4in2_4Gray4, 0, 0, 400, 300);
}
/////////////////////
void Dis_Cvet(int cvet){//раскраска экрана заданным цветом
for(int k=0;k<30000;k++){
if(cvet==3){bufer[k]=0b00000000;}//белый цвет
if(cvet==0){bufer[k]=0b11111111;}//чёрный цвет
if(cvet==2){bufer[k]=0b01010101;}//светло-серый цвет
if(cvet==1){bufer[k]=0b10101010;}// тёмно-серый цвет
}
}
/////////////////////
void Pixel(int x,int y,int cvet){//рисование пикселя по координатам заданным цветом
if(x<400&&y<300){
//bitWrite(value, bit, bitvalue) Ставит бит под номером bit в состояние bitvalue (0 или 1) в числе value
if(cvet==3){bitWrite(bufer[(2*400*y+2*x+1)/8],7-(2*400*y+2*x+1)%8 ,0);bitWrite(bufer[(2*400*y+2*x+1)/8],7-((2*400*y+2*x+1)%8)+1 ,0);}//белый цвет
if(cvet==0){bitWrite(bufer[(2*400*y+2*x+1)/8],7-(2*400*y+2*x+1)%8 ,1);bitWrite(bufer[(2*400*y+2*x+1)/8],7-((2*400*y+2*x+1)%8)+1 ,1);}//чёрный цвет
if(cvet==2){bitWrite(bufer[(2*400*y+2*x+1)/8],7-(2*400*y+2*x+1)%8 ,1);bitWrite(bufer[(2*400*y+2*x+1)/8],7-((2*400*y+2*x+1)%8)+1 ,0);}//светло-серый цвет
if(cvet==1){bitWrite(bufer[(2*400*y+2*x+1)/8],7-(2*400*y+2*x+1)%8 ,0);bitWrite(bufer[(2*400*y+2*x+1)/8],7-((2*400*y+2*x+1)%8)+1 ,1);}// тёмно-серый цвет
}
}
/////////////////////
Почему нужна +1 в выражение : bufer[(2400y+2*x+1)/8]? А без неё отображение не корректное.
С рисованием пикселя неясно, зато ясно с остальным - берём файл графики из библиотеки и просто заменяем рисование пикселя на свой вариант во всех желаем функциях типа отрезок, окружность, круг, квадрат, треугольник и т.д.
… видимо производители не писали под ардуино потому, что в ней невозможно вместить буфер экрана…Хотя есть же в ней и ESP32 и RP2040.
Спойлер
#include <SPI.h>
#include "epd4in2_V2.h"
#include "imagedata.h"
unsigned char bufer[30000];// массив для данных цвета пикселей экрана
Epd epd;
void setup() {
/////////////////////
epd.Init_4Gray();
//закраска всего экрана 4 цветами поочерёдно
Dis_Cvet(3);Buf_Ris();
delay(2000);
Dis_Cvet(2);Buf_Ris();
delay(2000);
Dis_Cvet(1);Buf_Ris();
delay(2000);
Dis_Cvet(0);Buf_Ris();
delay(2000);
//"шахматное поле 4 цвета"
for(int i=0;i<400;i++){
for(int j=0;j<300;j++){
if(i%60<30&&j%60<30){Pixel(i,j,0);}
if(i%60<60&&i%60>=30&&j%60<30){Pixel(i,j,2);}
if(i%60<60&&i%60>=30&&j%60>=30&&j%60<60){Pixel(i,j,1);}
if(i%60<30&&j%60>=30&&j%60<60){Pixel(i,j,3);}
}
}
Buf_Ris();
delay(3000);
//разноцветные отрезки-лучи
Dis_Cvet(1);
for(int i=0;i<400;i=i+20){
DrawLine(0, 0, i, 299, (i/20)%4);DrawLine(399, 0, i, 299, (i/20)%4);
if(i<300){ DrawLine(0, 0, 399, i,(i/20)%4); DrawLine(399, 0, 0, i,(i/20)%4);}
}
//
Buf_Ris();
delay(3000);
//вывод картинок одноцветных заданного цвета изображения и фона
Dis_Cvet(3);
drawBitmap(50,50,znak_2,96,96,3,2);
drawBitmap(150,100,znak_2,96,96,2,1);
drawBitmap(250,150,znak_2,96,96,3,0);
Buf_Ris();
delay(3000);
//вывод прямоугольников, окружностей, кругов
Dis_Cvet(3);
DrawRectangle(10,10,390,290,2);DrawRectangle(20,20,380,280,1);DrawRectangle(30,30,370,270,0);
DrawFilledRectangle(60,60,340,240,1);
DrawCircle(200,150,70,2); DrawCircle(200,150,60,0);DrawCircle(200,150,50,3);DrawFilledCircle(200,150,40,0);DrawFilledCircle(200,150,20,1);
Buf_Ris();
// epd.Clear();
////////////////
epd.Sleep();//отключение дисплея в сон
}
void loop() {
// put your main code here, to run repeatedly:
}
/////////////////////
void Buf_Ris(){//
epd.Buf_4GrayDisplay(bufer,0,0,400,300);// самописная функция на основе штатной epd.Set_4GrayDisplay(gImage_4in2_4Gray4, 0, 0, 400, 300);
}
/////////////////////
void Dis_Cvet(int cvet){//раскраска экрана заданным цветом
for(int k=0;k<30000;k++){
if(cvet==3){bufer[k]=0b00000000;}//белый цвет
if(cvet==0){bufer[k]=0b11111111;}//чёрный цвет
if(cvet==2){bufer[k]=0b01010101;}//светло-серый цвет
if(cvet==1){bufer[k]=0b10101010;}// тёмно-серый цвет
}
}
/////////////////////
void Pixel(int x,int y,int cvet){//рисование пикселя по координатам заданным цветом
if(x<400&&y<300){
//bitWrite(value, bit, bitvalue) Ставит бит под номером bit в состояние bitvalue (0 или 1) в числе value
if(cvet==3){bitWrite(bufer[(2*400*y+2*x+1)/8],7-(2*400*y+2*x+1)%8 ,0);bitWrite(bufer[(2*400*y+2*x+1)/8],7-((2*400*y+2*x+1)%8)+1 ,0);}//белый цвет
if(cvet==0){bitWrite(bufer[(2*400*y+2*x+1)/8],7-(2*400*y+2*x+1)%8 ,1);bitWrite(bufer[(2*400*y+2*x+1)/8],7-((2*400*y+2*x+1)%8)+1 ,1);}//чёрный цвет
if(cvet==2){bitWrite(bufer[(2*400*y+2*x+1)/8],7-(2*400*y+2*x+1)%8 ,1);bitWrite(bufer[(2*400*y+2*x+1)/8],7-((2*400*y+2*x+1)%8)+1 ,0);}//светло-серый цвет
if(cvet==1){bitWrite(bufer[(2*400*y+2*x+1)/8],7-(2*400*y+2*x+1)%8 ,0);bitWrite(bufer[(2*400*y+2*x+1)/8],7-((2*400*y+2*x+1)%8)+1 ,1);}// тёмно-серый цвет
}
}
/////////////////////
void DrawLine(int x0, int y0, int x1, int y1, int colored) {//рисование отрезка
/* Bresenham algorithm */
int dx = x1 - x0 >= 0 ? x1 - x0 : x0 - x1;
int sx = x0 < x1 ? 1 : -1;
int dy = y1 - y0 <= 0 ? y1 - y0 : y0 - y1;
int sy = y0 < y1 ? 1 : -1;
int err = dx + dy;
while((x0 != x1) && (y0 != y1)) {
//DrawPixel(x0, y0 , colored);
Pixel(x0,y0,colored);
if (2 * err >= dy) {
err += dy;
x0 += sx;
}
if (2 * err <= dx) {
err += dx;
y0 += sy;
}
}
}
/////////////////////
void DrawHorizontalLine(int x, int y, int line_width, int colored) {//рисование горизонтального отрезка
int i;
for (i = x; i < x + line_width; i++) {
Pixel(i, y, colored);
}
}
void DrawVerticalLine(int x, int y, int line_height, int colored) {//рисование вертикального отрезка
int i;
for (i = y; i < y + line_height; i++) {
Pixel(x, i, colored);
}
}
void DrawRectangle(int x0, int y0, int x1, int y1, int colored) {//рисование прямоугольника
int min_x, min_y, max_x, max_y;
min_x = x1 > x0 ? x0 : x1;
max_x = x1 > x0 ? x1 : x0;
min_y = y1 > y0 ? y0 : y1;
max_y = y1 > y0 ? y1 : y0;
DrawHorizontalLine(min_x, min_y, max_x - min_x + 1, colored);
DrawHorizontalLine(min_x, max_y, max_x - min_x + 1, colored);
DrawVerticalLine(min_x, min_y, max_y - min_y + 1, colored);
DrawVerticalLine(max_x, min_y, max_y - min_y + 1, colored);
}
void DrawFilledRectangle(int x0, int y0, int x1, int y1, int colored) {//рисование закрашенного прямоугольника
int min_x, min_y, max_x, max_y;
int i;
min_x = x1 > x0 ? x0 : x1;
max_x = x1 > x0 ? x1 : x0;
min_y = y1 > y0 ? y0 : y1;
max_y = y1 > y0 ? y1 : y0;
for (i = min_x; i <= max_x; i++) {
DrawVerticalLine(i, min_y, max_y - min_y + 1, colored);
}
}
void DrawCircle(int x, int y, int radius, int colored) {//рисование окружности
// Bresenham algorithm
int x_pos = -radius;
int y_pos = 0;
int err = 2 - 2 * radius;
int e2;
do {
Pixel(x - x_pos, y + y_pos, colored);
Pixel(x + x_pos, y + y_pos, colored);
Pixel(x + x_pos, y - y_pos, colored);
Pixel(x - x_pos, y - y_pos, colored);
e2 = err;
if (e2 <= y_pos) {
err += ++y_pos * 2 + 1;
if(-x_pos == y_pos && e2 <= x_pos) {
e2 = 0;
}
}
if (e2 > x_pos) {
err += ++x_pos * 2 + 1;
}
} while (x_pos <= 0);
}
void DrawFilledCircle(int x, int y, int radius, int colored) {//рисование круга
// Bresenham algorithm
int x_pos = -radius;
int y_pos = 0;
int err = 2 - 2 * radius;
int e2;
do {
Pixel(x - x_pos, y + y_pos, colored);
Pixel(x + x_pos, y + y_pos, colored);
Pixel(x + x_pos, y - y_pos, colored);
Pixel(x - x_pos, y - y_pos, colored);
DrawHorizontalLine(x + x_pos, y + y_pos, 2 * (-x_pos) + 1, colored);
DrawHorizontalLine(x + x_pos, y - y_pos, 2 * (-x_pos) + 1, colored);
e2 = err;
if (e2 <= y_pos) {
err += ++y_pos * 2 + 1;
if(-x_pos == y_pos && e2 <= x_pos) {
e2 = 0;
}
}
if(e2 > x_pos) {
err += ++x_pos * 2 + 1;
}
} while(x_pos <= 0);
}
/////////////////////
void drawBitmap(int16_t x, int16_t y,const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) {//вывод картинки по координатам, заданного размера и цветов изображения-фона
int16_t i, j, byteWidth = (w + 7) / 8;
uint8_t byte;
for(j=0; j<h; j++) {
for(i=0; i<w; i++ ) {
if(i & 7) byte <<= 1;
else byte = pgm_read_byte(bitmap + j * byteWidth + i / 8);
if(byte & 0x80) Pixel(x+i, y+j, color);
else Pixel(x+i, y+j, bg);
}
}
}
/////////////////////
Ну вот, доделал ПО китайцев как надо. Остались молчаливые недоделки на любителя, но это уже по необходимости, если возникнет ![]()
Пришёл модуль Pcf8563. Пока не работает. Время устанавливается, после повторной загрузки скетча с закоментированными строками настройки время сбрасывается в 11111…
Аналогично, после установки и отключения модуля.
Спойлер
/* Demonstration of Rtc_Pcf8563 Date Time individual functions.
* Set the clock to a time then loop over reading time and
* output the time and date to the serial console.
*
* I used a RBBB with Arduino IDE, the pins are mapped a
* bit differently. Change for your hw
* SCK - A5, SDA - A4, INT - D3/INT1
*
* After loading and starting the sketch, use the serial monitor
* to see the clock output.
*
* setup: see Pcf8563 data sheet.
* 1x 10Kohm pullup on Pin3 INT
* No pullups on Pin5 or Pin6 (I2C internals used)
* 1x 0.1pf on power
* 1x 32khz chrystal
*
* Joe Robertson, jmr
* orbitalair@gmail.com
*/
#include <Wire.h>
#include "Rtc_Pcf8563.h"
//SDA-A4,SCL-A5
//init the real time clock
Rtc_Pcf8563 rtc;
void setup()
{
Serial.begin(9600);
// Serial.println("Date and Time function test.");
//clear out the registers
rtc.initClock();
//set a time to start with.
//day, weekday, month, century(1=1900, 0=2000), year(0-99)
rtc.setDate(10, 6, 11, 1, 24);
//hr, min, sec
rtc.setTime(12, 7, 45);
// Serial.println("Date set to: Sunday(6) March(3) 14, 2010. Time set to: 1:15:00 am.");
// Serial.println("Now reading back from chip.");
}
void loop()
{
//both format functions call the internal getTime() so that the
//formatted strings are at the current time/date.
Serial.print("Hour:");
Serial.println(rtc.getHour());
Serial.print("Minute:");
Serial.println(rtc.getMinute());
Serial.print("Second:");
Serial.println(rtc.getSecond());
Serial.print("Weekday:");
Serial.println(rtc.getWeekday());
Serial.print("Day:");
Serial.println(rtc.getDay());
Serial.print("Month:");
Serial.println(rtc.getMonth());
Serial.print("Year:");
Serial.println(rtc.getYear());
delay(1000);
}
А кварц то внешний!
Да, снаружи баллончик с ножками.









