Расстояние там было 8 см? При частоте камня в 24мгц, длительность одного такта = 41.7 нс. Если какая-то волшебная пуля пройдет за это время 8см, то ее скорость должна будет составлять около 2 тысяч километров в секунду (1920, если точно). Двигаясь с подобной скоростью, пуля длиной три миллиметра перекроет датчик на 1.56 наносекунды. Датчики должны обеспечивать отклик на частотах до 0.64 гГц. В принципе, есть ультрабыстрые фотодиоды, которые вполне могли бы работать в этой полосе, но сигнал с них надо вытягивать до логического уровня, что потребует весьма нетривиальных усилий. В этой связи мне кажется, что со стороны датчиков ограничения возникнут гораздо раньше, чем тактовой атмеги перестанет хватать.
а ограниченая раньше возникнут. но никто не проверял от чего быстрее. частоты камняне хватало, или уже датчики не успевали. для этого нужна наверно воздушка с накачкой, чтобы можно было проверить при разных скоростях
ага. страшно))) интересно как работает. белые пластины отражатель который чем то засвечивают, возможно ик диапазон
так как отследить точку на таком расстоянии обычными фотодиодами нереально, значит используется камера, 1*96 пикселей например, или выше разрешение. но она должна быть высокоскоростная, да и процессор обрабатывающий тоже
серьезный аппарат. стоит наверно тоже соответственно
да и у многих ли есть огнестрел. да и зачем его постоянно обмерять
вот понимаю что гаусс расчету точному не поддается, все равно нужно эксперименты ставить чтобы добится лучших результатов, а тут без хронометра не обойтись
....... Включает в себя хронограф, ИК светодиодная комплект ........
....... Более высокая точность была достигнута с помощью высокого процессор скорость 48 МГц ........
Для измерения скорости пули нужно стрелять сквозь треугольные рабочие зоны хронографа. Под рабочими зонами прибора расположены фотодатчики, которые определяют точное время пролета пули. Caldwell BALLISTIC PRECISION определяет скорости пуль в диапазоне от 1,5 до 3 047 м/с с погрешностью ±0,25%. Возможно также проводить измерения в фут/с. Такая высокая точность измерений достигается использованием в хронографе высокоскоростного процессора 48 МГц.
если бы мне дали этот код я бы сам наверно не стал особо разбираться, глянул только идею и сам бы написал, это часто проще чем в чьем-то коде разобраться
Я пока собрал в виде макета на arduino pro micro (ATmega32U4), залил скетч выложенный здесь. Пока полазил по менушке и вроде все отлично, но есть пару вопросов.
1.Когда переходиш по пунктам меню, то в момент перехода с пункта на пункт промаргивает не однородно закрашенный черный экран. Так у всех или только у меня?
2. В программе хорошо видно, какие выводы управляют экраном, а какие кнопками и их можно переназначить. А где в программе видно, что именно выводы 2 и 3 отвечают за обработку фототранзисторов и можно ли их переназначить на другие выводы?.
2 и 3 пины это прерывания: в файле main 2 и 3 строка
посмотрел немного свой код, нашел ряд не очень оптимальных решений. например в функцию отрисовки экрана не обязательно передавать пункт меню, смысла нет, так как переменная все равно глобальная.
можно ускорить отрисовку экрана. поменять функцию SendByte на эту:
Не знаю интересна вам еще эта тема или нет, но вы как то спрашивали в этом форуме предложения по отрисовке уровня заряда батареи. Так вот если еще интересно, то уровень заряда можно отображать просто в процентах от 0% до 100% в окне количества измерений.
Кажатся нашел, я так понимаю этот код считывает и отображает уровень заряда
//считаем напряжение
void napr(){
U = analogRead(accum);
U = constrain(U, 547, 614);
U = map(U, 547, 614, 0, 9);
Goto_XY(80,0);
for (int i = 0; i<3; i++){
SendByte(1,pgm_read_byte(&(batt[i])));
}
if (U == 9){
for (int i = 0; i<9; i++){
SendByte(1,pgm_read_byte(&(batt[3])));
}
}
if (U<9){
for (int i = 0; i<(9-U); i++){
SendByte(1,pgm_read_byte(&(batt[2])));
}
for (int i = 0; i<U; i++){
SendByte(1,pgm_read_byte(&(batt[3])));
}
}
SendByte(1,pgm_read_byte(&(batt[2])));
SendByte(1,pgm_read_byte(&(batt[1])));
}
Так и я хочу Li-ion аккумулятор запитать через Step-UP преобразователь. Только буду мерять напряжение на самом аккумуляторе (от 3в до 4,2В), а иначе смысл мерить постоянно 5В.
Это понятно что опытным путем, меняете напряжение на входе и видите, что видит АЦП в цифрах. Не с потолка же взяли эти числа ))) Я пока просто учусь. Вот и думаю как посмотреть что видит АЦП в реальном времени и ест ли такие средства у ардуины? Или я не правильно понял принцип?
Уважаемый jeka_tm, не подскажите мне в чем проблема?
Решил модернизировать вашу программку Speed_v5.9.8 в части отслеживания уровня заряда батареи, я для этого решил пожертвовать счетчиком количества измерени который в верхнем правом углу. Эту шкалу делений использовал для отображения уровня заряда, и вроде бы работает, но не в реальном времени, т.е. шкала обнавляется если выйти в другое меню и потом вернуться на главное. Не подскажите, что в коде не так? Код двух вкладок ниже. Пробовал провести несколько делитанский экспериментов, а именно Window_0 сунуть в loop (), тогда конечно в реале все показывает, но не перейдешь в другии меню. Был бы весьма вам признателен за помощь.
//добавил в вкладке Speed_v5.9.8.ino
//считаем напряжение
#define accum A0
int U = 0;
int a = 0;
void battary() {
U = analogRead(accum);
U = constrain(U, 650, 855);
U = map(U, 650, 855, 0, 9);
for( a=0;a<=U;a++) fillRect(5+a*4, 3, 3, 8, color);
}
расстояние между датчиками, частота ардуины
А можно под редактировать код чтобы можно было выбрать вес пули до сотой грамма. А то в страйкболом используются пули с таким весом.
Например 0.23, 0.25, 0,28, 0.32
И еще о индикации заряда батареи, как понимаю она еще в разработке или решили не реализовывать ее?
ну если скажешь куда вставить индикацию зарядки батареи, а лучше дорисуй в пайнте можно и сделать))
вот интересно какой максимальный вес пули?
Расстояние там было 8 см? При частоте камня в 24мгц, длительность одного такта = 41.7 нс. Если какая-то волшебная пуля пройдет за это время 8см, то ее скорость должна будет составлять около 2 тысяч километров в секунду (1920, если точно). Двигаясь с подобной скоростью, пуля длиной три миллиметра перекроет датчик на 1.56 наносекунды. Датчики должны обеспечивать отклик на частотах до 0.64 гГц. В принципе, есть ультрабыстрые фотодиоды, которые вполне могли бы работать в этой полосе, но сигнал с них надо вытягивать до логического уровня, что потребует весьма нетривиальных усилий. В этой связи мне кажется, что со стороны датчиков ограничения возникнут гораздо раньше, чем тактовой атмеги перестанет хватать.
вот интересно какой максимальный вес пули?
Минимальный 0.1 но японцы в основном для своих пистолетов продают 0.12 (скорость выстрела в районе 68-80 М/с)
a5021 у меня в датчиках 70мм
а ограниченая раньше возникнут. но никто не проверял от чего быстрее. частоты камняне хватало, или уже датчики не успевали. для этого нужна наверно воздушка с накачкой, чтобы можно было проверить при разных скоростях
Helgi000 я спрашивал про максимальный
Для пневматики 4.5 самые тяжелые это юджин 1.12 грамма, дла охотничьей пневматики 9мм - самый тяжелый 9.5 грамм.
всего то. ладно как время будет переделаю. там еще все равно для расчета энергии нужно дописывать
Модераторы ! Отпишите меня от уведомлений в этой теме ! Никакие кнопки не помогают ))
Пардон за ОФФТОП
Потестил наконец хронометр. пистолет пм
Убило кого-нибудь ? :)
нет))
У вас обнаружились опасные конкуренты. :)
видео
ага. страшно))) интересно как работает. белые пластины отражатель который чем то засвечивают, возможно ик диапазон
так как отследить точку на таком расстоянии обычными фотодиодами нереально, значит используется камера, 1*96 пикселей например, или выше разрешение. но она должна быть высокоскоростная, да и процессор обрабатывающий тоже
но это мое предположение
Как я понял, это все же инфракрасные зеркальца. Заявлены измеряемые скорости до 3 тыс. м. / сек.
серьезный аппарат. стоит наверно тоже соответственно
да и у многих ли есть огнестрел. да и зачем его постоянно обмерять
вот понимаю что гаусс расчету точному не поддается, все равно нужно эксперименты ставить чтобы добится лучших результатов, а тут без хронометра не обойтись
А я так думаю, что описанная в этой ветке конструкция не особо и хуже.
этот хронометр такие скорости не сможет измерить. нужно ставить более быстрый процессор, да и датчики такие скорее всего не успеют
но для любителей пневматики и гауссов подходит))
Про датчики и процессор я уже здесь умствовал, т.ч. с этим, как раз, все понятно. Важно, что сам принцип и примененный подход работают.
ага)
А можно выложить исхлодник рисующий управляющий меню ?
Как я понял, это все же инфракрасные зеркальца. Заявлены измеряемые скорости до 3 тыс. м. / сек.
есть прорези ( две ) для ИК-барьеров , крылья - не держатели антенн , а отражатели
усы "антенн" - не антенны , а держатели отражателей
...и быстрый процессор
я думаю это обычные конденсаторы (усы эти),может в составе контура.
под углом они просто для удобства
а дальше стоят все теже два компаратора (пиковых детектора) всё.
ИК и отражатель тоже версия нормальная, даже более реальная
но я думая в щелях СВЧ излучатель\приёмник на 1 транзисторе а парус отражатель
при проходе свч контур меняет параметры,а дальше теже компараторы
хотя для этого варианта не нужен отражатель,от пули в любом случае изменится параметр СВЧ контура
....... Включает в себя хронограф, ИК светодиодная комплект ........
....... Более высокая точность была достигнута с помощью высокого процессор скорость 48 МГц ........
Для измерения скорости пули нужно стрелять сквозь треугольные рабочие зоны хронографа. Под рабочими зонами прибора расположены фотодатчики, которые определяют точное время пролета пули. Caldwell BALLISTIC PRECISION определяет скорости пуль в диапазоне от 1,5 до 3 047 м/с с погрешностью ±0,25%. Возможно также проводить измерения в фут/с. Такая высокая точность измерений достигается использованием в хронографе высокоскоростного процессора 48 МГц.
А можно выложить исхлодник рисующий управляющий меню ?
это как?
А можно выложить исхлодник рисующий управляющий меню ?
это как?
ну как, там же есть в программе модуль отображения меню, библиотека работы с дислпеем...
вот этот кусок и надо.
Кусок ккоторый делает вот это:
http://arduino.ru/sites/default/files/resize/u4939/wp_20150330_22_57_54_...
//======================================================================== // Управление первой кнопкой //======================================================================== if(digitalRead(pin_1)==0 && digitalRead(pin_2)==1){ delay(50); if(digitalRead(pin_1)==0 && digitalRead(pin_2)==1){ test=0; switch (display_N) { case 0: // если главный экран display_N=2; Window_2(display_2_menu); delay(200); break; case 1: // если экран статистики display_N=0; Window_0(); delay(200); break; case 2: // если меню настроек display_2_menu++; if(display_2_menu==5) display_2_menu=0; Window_2(display_2_menu); delay(200); break; case 3: // если экран калибровки display_3_menu++; if(display_3_menu==3) display_3_menu=0; Window_3(display_3_menu); delay(200); break; case 4: // если настройка масса display_4_menu++; if(display_4_menu==3) display_4_menu=0; Window_4(display_4_menu); delay(200); break; } } } //======================================================================== // Управление второй кнопкой //======================================================================== if(digitalRead(pin_2)==0 && digitalRead(pin_1)==1){ delay(50); if(digitalRead(pin_2)==0 && digitalRead(pin_1)==1){ test=0; switch (display_N) { case 0: first(); break; case 1: Stat(); break; case 2: Settints(); break; case 3: Calibr(); break; case 4: massa(); break; } } } if(test) Test(); } //======================================================================== // Главный экран //======================================================================== void first(){ display_N=1; Window_1(); } //======================================================================== // Экран статистики //======================================================================== void Stat(){ for(byte i=0;i<10;i++){ DATA [i]=0; } middle=0; Window_1(); } //======================================================================== // Экран настроек //======================================================================== void Settints(){ switch (display_2_menu) { case 0: // переходим в калибровку display_N=3; Window_3(display_3_menu); delay(200); break; case 1: // Настройка массы display_N=4; Window_4(display_4_menu); delay(200); break; case 2: // Скорость/энергия energi=!energi; EEPROM.write(adr_energi, energi); Window_2(display_2_menu); break; case 3: // Инвертирование color=!color; EEPROM.write(adr_color, color); Window_2(display_2_menu); break; case 4: // Назад display_N=0; display_2_menu=0; Window_0(); delay(200); break; } } //======================================================================== // Экран калибровки //======================================================================== void Calibr(){ switch (display_3_menu) { case 0: if(calibration<254) calibration++; Window_3(display_3_menu); break; case 1: if(calibration>0) calibration--; Window_3(display_3_menu); break; case 2: display_N=2; Window_2(display_2_menu); display_3_menu=0; delay(200); EEPROM.write(adr_calibr, calibration); break; } } //======================================================================== // Управление массой //======================================================================== void massa(){ switch (display_4_menu) { case 0: if(mass<250) mass++; Window_4(display_4_menu); break; case 1: if(mass>0) mass--; Window_4(display_4_menu); break; case 2: display_N=2; Window_2(display_2_menu); display_4_menu=0; delay(200); EEPROM.write(adr_mass, mass); break; } } //======================================================================== // Экран настроек //======================================================================== void Window_2(byte i){ fillScreen(!color); byte n=1; n=n<<i; Menu( 1, myStrings[0], n&1); Menu( 12, myStrings[1], n&2); if(energi) Menu( 23, myStrings[3], n&4); else Menu( 23, myStrings[2], n&4); Menu( 33, myStrings[4], n&8); Menu( 44, myStrings[5], n&16); Update(); }я хз разберешься или нет. я объяснять не буду
а сама библиотека работы с дисплеем 1202 ?
самописная или чья-то готовая или от n1100 ?
самописная, часть кода бралась из библиотек
если бы мне дали этот код я бы сам наверно не стал особо разбираться, глянул только идею и сам бы написал, это часто проще чем в чьем-то коде разобраться
Не нашёл тут как личные сообщения отправлять...
а можно как-то договориться сюда (на форум) выложить полностью модуль работы с менюхами и экраном ?
Думаю людям будет полезно, ускорятся реализации народных поделок
экран 1202 довольно хорош этот - дёшев,доступен и припаивается хорошо.
можно просто при нажатии на меню загорится светодиод на пине том или ином.
а один из пунктов переход на другой экран меню
ну или просто вырезать из вашего проекта если совсем нет времени и желания.
или за денежку как-то договориться оформить модуль
можно почтой пообщаться: selevo@mail.ru
да вот весь проект. В том виде как есть, даже с разбивкой по файлам. Разбирайся
Speed_v5.9.8
#include <avr/pgmspace.h> #include <EEPROM.h> #define pgm pgm_read_byte #define CS 7 #define Data 6 #define Clock 5 #define LCD_X 96 #define LCD_Y 68 #define LCD_String 9 #define swap(a, b) { int t = a; a = b; b = t; } #define SetYAddr 0xB0 #define SetXAddr4 0x00 #define SetXAddr3 0x10 #define LCD_D 1 #define LCD_C 0 #define pin_1 A2 #define pin_2 A4 #define W 94 #define H 66 #define adr_first 0 #define adr_calibr 2 #define adr_mass 4 #define adr_energi 6 #define adr_color 8 #define adr_safe 10 volatile unsigned long time1 = 0; //Время срабатывания первого датчика volatile unsigned long time2 = 0; //Время срабатывания второго volatile unsigned long skorost = 0; //временное число volatile unsigned long factor = 10000; //Множитель volatile bool flag1 = 1; volatile bool flag2 = 1; long middle = 0; byte n=0; byte S = 1; byte display_N = 0; byte display_2_menu = 0; byte display_3_menu = 0; byte display_4_menu = 0; byte display_5_menu = 0; byte calibration; byte mass; byte energi; byte color; byte test=0; char* myStrings[8]={ "Калибровка", "Масса", "Скорость", "Энергия", "Инверсия", "Назад", "+", "-"}; int DATA [10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; byte LCD_RAM[LCD_X*LCD_String]; void Start(){ // 1 прерывание if(flag1==1){ time1=micros(); flag1=0; } } void End(){ // 2 прерывание if(flag2==1){ time2=micros(); flag2=0; } }Font
static const char font[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00 , // 0x20 space 0x00, 0x00, 0x5f, 0x00, 0x00 , // 0x21 ! 0x00, 0x07, 0x00, 0x07, 0x00 , // 0x22 " 0x14, 0x7f, 0x14, 0x7f, 0x14 , // 0x23 # 0x24, 0x2a, 0x7f, 0x2a, 0x12 , // 0x24 $ 0x23, 0x13, 0x08, 0x64, 0x62 , // 0x25 % 0x36, 0x49, 0x55, 0x22, 0x50 , // 0x26 & 0x00, 0x05, 0x03, 0x00, 0x00 , // 0x27 ' 0x00, 0x1c, 0x22, 0x41, 0x00 , // 0x28 ( 0x00, 0x41, 0x22, 0x1c, 0x00 , // 0x29 ) 0x14, 0x08, 0x3e, 0x08, 0x14 , // 0x2a * 0x08, 0x08, 0x3e, 0x08, 0x08 , // 0x2b + 0x00, 0x50, 0x30, 0x00, 0x00 , // 0x2c , 0x08, 0x08, 0x08, 0x08, 0x08 , // 0x2d - 0x00, 0x60, 0x60, 0x00, 0x00 , // 0x2e . 0x20, 0x10, 0x08, 0x04, 0x02 , // 0x2f / 0x3e, 0x51, 0x49, 0x45, 0x3e , // 0x30 0 0x00, 0x42, 0x7f, 0x40, 0x00 , // 0x31 1 0x42, 0x61, 0x51, 0x49, 0x46 , // 0x32 2 0x21, 0x41, 0x45, 0x4b, 0x31 , // 0x33 3 0x18, 0x14, 0x12, 0x7f, 0x10 , // 0x34 4 0x27, 0x45, 0x45, 0x45, 0x39 , // 0x35 5 0x3c, 0x4a, 0x49, 0x49, 0x30 , // 0x36 6 0x01, 0x71, 0x09, 0x05, 0x03 , // 0x37 7 0x36, 0x49, 0x49, 0x49, 0x36 , // 0x38 8 0x06, 0x49, 0x49, 0x29, 0x1e , // 0x39 9 0x00, 0x36, 0x36, 0x00, 0x00 , // 0x3a : 0x00, 0x56, 0x36, 0x00, 0x00 , // 0x3b ; 0x08, 0x14, 0x22, 0x41, 0x00 , // 0x3c < 0x14, 0x14, 0x14, 0x14, 0x14 , // 0x3d = 0x00, 0x41, 0x22, 0x14, 0x08 , // 0x3e > 0x02, 0x01, 0x51, 0x09, 0x06 , // 0x3f ? 0x32, 0x49, 0x79, 0x41, 0x3e , // 0x40 @ 0x7e, 0x11, 0x11, 0x11, 0x7e , // 0x41 A 0x7f, 0x49, 0x49, 0x49, 0x36 , // 0x42 B 0x3e, 0x41, 0x41, 0x41, 0x22 , // 0x43 C 0x7f, 0x41, 0x41, 0x22, 0x1c , // 0x44 D 0x7f, 0x49, 0x49, 0x49, 0x41 , // 0x45 E 0x7f, 0x09, 0x09, 0x09, 0x01 , // 0x46 F 0x3e, 0x41, 0x49, 0x49, 0x7a , // 0x47 G 0x7f, 0x08, 0x08, 0x08, 0x7f , // 0x48 H 0x00, 0x41, 0x7f, 0x41, 0x00 , // 0x49 I 0x20, 0x40, 0x41, 0x3f, 0x01 , // 0x4a J 0x7f, 0x08, 0x14, 0x22, 0x41 , // 0x4b K 0x7f, 0x40, 0x40, 0x40, 0x40 , // 0x4c L 0x7f, 0x02, 0x0c, 0x02, 0x7f , // 0x4d M 0x7f, 0x04, 0x08, 0x10, 0x7f , // 0x4e N 0x3e, 0x41, 0x41, 0x41, 0x3e , // 0x4f O 0x7f, 0x09, 0x09, 0x09, 0x06 , // 0x50 P 0x3e, 0x41, 0x51, 0x21, 0x5e , // 0x51 Q 0x7f, 0x09, 0x19, 0x29, 0x46 , // 0x52 R 0x46, 0x49, 0x49, 0x49, 0x31 , // 0x53 S 0x01, 0x01, 0x7f, 0x01, 0x01 , // 0x54 T 0x3f, 0x40, 0x40, 0x40, 0x3f , // 0x55 U 0x1f, 0x20, 0x40, 0x20, 0x1f , // 0x56 V 0x3f, 0x40, 0x38, 0x40, 0x3f , // 0x57 W 0x63, 0x14, 0x08, 0x14, 0x63 , // 0x58 X 0x07, 0x08, 0x70, 0x08, 0x07 , // 0x59 Y 0x61, 0x51, 0x49, 0x45, 0x43 , // 0x5a Z 0x00, 0x7f, 0x41, 0x41, 0x00 , // 0x5b [ 0x02, 0x04, 0x08, 0x10, 0x20 , // 0x5c backslash 0x00, 0x41, 0x41, 0x7f, 0x00 , // 0x5d ] 0x04, 0x02, 0x01, 0x02, 0x04 , // 0x5e ^ 0x40, 0x40, 0x40, 0x40, 0x40 , // 0x5f _ 0x00, 0x01, 0x02, 0x04, 0x00 , // 0x60 ` 0x20, 0x54, 0x54, 0x54, 0x78 , // 0x61 a 0x7f, 0x48, 0x44, 0x44, 0x38 , // 0x62 b 0x38, 0x44, 0x44, 0x44, 0x20 , // 0x63 c 0x38, 0x44, 0x44, 0x48, 0x7f , // 0x64 d 0x38, 0x54, 0x54, 0x54, 0x18 , // 0x65 e 0x08, 0x7e, 0x09, 0x01, 0x02 , // 0x66 f 0x0c, 0x52, 0x52, 0x52, 0x3e , // 0x67 g 0x7f, 0x08, 0x04, 0x04, 0x78 , // 0x68 h 0x00, 0x44, 0x7d, 0x40, 0x00 , // 0x69 i 0x20, 0x40, 0x44, 0x3d, 0x00 , // 0x6a j 0x7f, 0x10, 0x28, 0x44, 0x00 , // 0x6b k 0x00, 0x41, 0x7f, 0x40, 0x00 , // 0x6c l 0x7c, 0x04, 0x18, 0x04, 0x78 , // 0x6d m 0x7c, 0x08, 0x04, 0x04, 0x78 , // 0x6e n 0x38, 0x44, 0x44, 0x44, 0x38 , // 0x6f o 0x7c, 0x14, 0x14, 0x14, 0x08 , // 0x70 p 0x08, 0x14, 0x14, 0x18, 0x7c , // 0x71 q 0x7c, 0x08, 0x04, 0x04, 0x08 , // 0x72 r 0x48, 0x54, 0x54, 0x54, 0x20 , // 0x73 s 0x04, 0x3f, 0x44, 0x40, 0x20 , // 0x74 t 0x3c, 0x40, 0x40, 0x20, 0x7c , // 0x75 u 0x1c, 0x20, 0x40, 0x20, 0x1c , // 0x76 v 0x3c, 0x40, 0x30, 0x40, 0x3c , // 0x77 w 0x44, 0x28, 0x10, 0x28, 0x44 , // 0x78 x 0x0c, 0x50, 0x50, 0x50, 0x3c , // 0x79 y 0x44, 0x64, 0x54, 0x4c, 0x44 , // 0x7a z 0x00, 0x08, 0x36, 0x41, 0x00 , // 0x7b { 0x00, 0x00, 0x7f, 0x00, 0x00 , // 0x7c | 0x00, 0x41, 0x36, 0x08, 0x00 , // 0x7d } 0x10, 0x08, 0x08, 0x10, 0x08 , // 0x7e ~ 0x00, 0x00, 0x00, 0x00, 0x00 , // 0x7f 0x7e, 0x11, 0x11, 0x11, 0x7e , // 0x80 A // Русские символы 0x7f, 0x49, 0x49, 0x49, 0x33 , // 0x81 Б 0x7f, 0x49, 0x49, 0x49, 0x36 , // 0x82 В 0x7f, 0x01, 0x01, 0x01, 0x03 , // 0x83 Г 0xe0, 0x51, 0x4f, 0x41, 0xff , // 0x84 Д 0x7f, 0x49, 0x49, 0x49, 0x41 , // 0x85 E 0x77, 0x08, 0x7f, 0x08, 0x77 , // 0x86 Ж 0x41, 0x49, 0x49, 0x49, 0x36 , // 0x87 З 0x7f, 0x10, 0x08, 0x04, 0x7f , // 0x88 И 0x7c, 0x21, 0x12, 0x09, 0x7c , // 0x89 Й 0x7f, 0x08, 0x14, 0x22, 0x41 , // 0x8A K 0x20, 0x41, 0x3f, 0x01, 0x7f , // 0x8B Л 0x7f, 0x02, 0x0c, 0x02, 0x7f , // 0x8C M 0x7f, 0x08, 0x08, 0x08, 0x7f , // 0x8D H 0x3e, 0x41, 0x41, 0x41, 0x3e , // 0x8E O 0x7f, 0x01, 0x01, 0x01, 0x7f , // 0x8F П 0x7f, 0x09, 0x09, 0x09, 0x06 , // 0x90 P 0x3e, 0x41, 0x41, 0x41, 0x22 , // 0x91 C 0x01, 0x01, 0x7f, 0x01, 0x01 , // 0x92 T 0x47, 0x28, 0x10, 0x08, 0x07 , // 0x93 У 0x1c, 0x22, 0x7f, 0x22, 0x1c , // 0x94 Ф 0x63, 0x14, 0x08, 0x14, 0x63 , // 0x95 X 0x7f, 0x40, 0x40, 0x40, 0xff , // 0x96 Ц 0x07, 0x08, 0x08, 0x08, 0x7f , // 0x97 Ч 0x7f, 0x40, 0x7f, 0x40, 0x7f , // 0x98 Ш 0x7f, 0x40, 0x7f, 0x40, 0xff , // 0x99 Щ 0x01, 0x7f, 0x48, 0x48, 0x30 , // 0x9A Ъ 0x7f, 0x48, 0x30, 0x00, 0x7f , // 0x9B Ы 0x00, 0x7f, 0x48, 0x48, 0x30 , // 0x9C Э 0x22, 0x41, 0x49, 0x49, 0x3e , // 0x9D Ь 0x7f, 0x08, 0x3e, 0x41, 0x3e , // 0x9E Ю 0x46, 0x29, 0x19, 0x09, 0x7f , // 0x9F Я 0x20, 0x54, 0x54, 0x54, 0x78 , // 0xA0 a 0x3c, 0x4a, 0x4a, 0x49, 0x31 , // 0xA1 б 0x7c, 0x54, 0x54, 0x54, 0x28 , // 0xA2 в 0x7c, 0x04, 0x04, 0x04, 0x0c , // 0xA3 г 0xe0, 0x54, 0x4c, 0x44, 0xfc , // 0xA4 д 0x38, 0x54, 0x54, 0x54, 0x18 , // 0xA5 e 0x6c, 0x10, 0x7c, 0x10, 0x6c , // 0xA6 ж 0x44, 0x44, 0x54, 0x54, 0x28 , // 0xA7 з 0x7c, 0x20, 0x10, 0x08, 0x7c , // 0xA8 и 0x7c, 0x41, 0x22, 0x11, 0x7c , // 0xA9 й 0x7c, 0x10, 0x10, 0x28, 0x44 , // 0xAA к 0x20, 0x44, 0x3c, 0x04, 0x7c , // 0xAB л 0x7c, 0x08, 0x10, 0x08, 0x7c , // 0xAC м 0x7c, 0x10, 0x10, 0x10, 0x7c , // 0xAD н 0x38, 0x44, 0x44, 0x44, 0x38 , // 0xAE o 0x7c, 0x04, 0x04, 0x04, 0x7c , // 0xAF п 0x7C, 0x14, 0x14, 0x14, 0x08 , // 0xB0 p 0x38, 0x44, 0x44, 0x44, 0x20 , // 0xB1 c 0x04, 0x04, 0x7c, 0x04, 0x04 , // 0xB2 т 0x0C, 0x50, 0x50, 0x50, 0x3C , // 0xB3 у 0x30, 0x48, 0xfc, 0x48, 0x30 , // 0xB4 ф 0x44, 0x28, 0x10, 0x28, 0x44 , // 0xB5 x 0x7c, 0x40, 0x40, 0x40, 0xfc , // 0xB6 ц 0x0c, 0x10, 0x10, 0x10, 0x7c , // 0xB7 ч 0x7c, 0x40, 0x7c, 0x40, 0x7c , // 0xB8 ш 0x7c, 0x40, 0x7c, 0x40, 0xfc , // 0xB9 щ 0x04, 0x7c, 0x50, 0x50, 0x20 , // 0xBA ъ 0x7c, 0x50, 0x50, 0x20, 0x7c , // 0xBB ы 0x7c, 0x50, 0x50, 0x20, 0x00 , // 0xBC ь 0x28, 0x44, 0x54, 0x54, 0x38 , // 0xBD э 0x7c, 0x10, 0x38, 0x44, 0x38 , // 0xBE ю 0x08, 0x54, 0x34, 0x14, 0x7c , // 0xBF я }; //цифры размером 16х32 пикселей static const char mass16x32[10][64] PROGMEM ={ { 0xF8, 0xFC, 0xFA, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xFA, 0xFC, 0xF8, //0 0x3F, 0x7F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7F, 0x3F, 0xFE, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFE, 0x1F, 0x3F, 0x5F, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x5F, 0x3F, 0x1F}, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFC, 0xF8, //1 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x3F, 0x1F}, { 0x00, 0x00, 0x02, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xFA, 0xFC, 0xF8, //2 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xBF, 0x7F, 0x3F, 0xFE, 0xFF, 0xFE, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x3F, 0x5F, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x40, 0x00, 0x00}, { 0x00, 0x00, 0x02, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xFA, 0xFC, 0xF8, //3 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xBF, 0x7F, 0x3F, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFE, 0xFF, 0xFE, 0x00, 0x00, 0x40, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x5F, 0x3F, 0x1F}, { 0xF8, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFC, 0xF8, //4 0x3F, 0x7F, 0xBF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xBF, 0x7F, 0x3F, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFE, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x3F, 0x1F}, { 0xF8, 0xFC, 0xFA, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x02, 0x00, 0x00, //5 0x3F, 0x7F, 0xBF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFE, 0xFF, 0xFE, 0x00, 0x00, 0x40, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x5F, 0x3F, 0x1F}, { 0xF8, 0xFC, 0xFA, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x02, 0x00, 0x00, //6 0x3F, 0x7F, 0xBF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0xFE, 0xFF, 0xFE, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFE, 0xFF, 0xFE, 0x1F, 0x3F, 0x5F, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x5F, 0x3F, 0x1F}, { 0x00, 0x00, 0x02, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xFA, 0xFC, 0xF8, //7 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x3F, 0x1F}, { 0xF8, 0xFC, 0xFA, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xFA, 0xFC, 0xF8, //8 0x3F, 0x7F, 0xBF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xBF, 0x7F, 0x3F, 0xFE, 0xFF, 0xFE, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFE, 0xFF, 0xFE, 0x1F, 0x3F, 0x5F, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x5F, 0x3F, 0x1F}, { 0xF8, 0xFC, 0xFA, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xFA, 0xFC, 0xF8, //9 0x3F, 0x7F, 0xBF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xBF, 0x7F, 0x3F, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFE, 0xFF, 0xFE, 0x00, 0x00, 0x40, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x5F, 0x3F, 0x1F}}; //цифры размером 10х16 пикселей static const char mass10x16[10][20] PROGMEM ={ {0x7E, 0x3D, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3D, 0x7E, // 0 0x7F, 0xBE, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xBE, 0x7F}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, // 1 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE}, {0x00, 0x81, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xBD, 0x7E, // 2 0x7F, 0xBE, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x80, 0x00}, {0x00, 0x81, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xBD, 0x7E, // 3 0x00, 0x80, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xBE, 0x7F}, {0x7E, 0xBC, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xBC, 0x7E, // 4 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x3E, 0x7F}, {0x7E, 0xBD, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x81, 0x00, // 5 0x00, 0x80, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xBE, 0x7F}, {0x7E, 0xBD, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x81, 0x00, // 6 0x7F, 0xBE, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xBE, 0x7F}, {0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3D, 0x7E, // 7 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7F}, {0x7E, 0xBD, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xBD, 0x7E, // 8 0x7F, 0xBE, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xBE, 0x7F}, {0x7E, 0xBD, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xBD, 0x7E, // 9 0x00, 0x80, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xBE, 0x7F} }; //картинка линия под которой написано m/s static const char image[48] PROGMEM ={ 0x00, 0x04, 0xE4, 0xC4, 0x84, 0x04, 0x84, 0xC4, 0xE4, 0x04, 0x04, 0x04, 0x04, 0x84, 0xE4, 0x04, 0xC4, 0x64, 0x24, 0x24, 0x64, 0xC4, 0x04, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x01, 0x03, 0x01, 0x00, 0xFF, 0x00, 0xE0, 0x38, 0x0E, 0x03, 0x00, 0x00, 0x61, 0xC3, 0x82, 0x86, 0xCC, 0x78, 0x00, 0x00};LCD
//======================================================================== // Графические функции //======================================================================== /* Clear_LCD(); Update(); fillScreen(color); drawPixel (x, y, color); drawChar(x, y, color, char c); drawString(x, y, color, char *str); drawLine(x0, y0, x1, y1, color); drawFastVLine(x, y, h, color); drawFastHLine(x, y, w, color); drawRect(x, y, w, h, color); drawCircle(x0, y0, r, color); drawRoundRect(x, y, w, h, r, color); drawTriangle(x0, y0, x1, y1, x2, y2, color); drawCircleHelper(x0, y0, r, cornername, color); fillCircle(x0, y0, r, color); fillCircleHelper(x0, y0, r, cornername, delta, color); fillRect(x, y, w, h, color); fillRoundRect(x, y, w, h, r, color); fillTriangle(x0, y0, x1, y1, x2, y2, color); drawBitmap(x, y, const uint8_t *bitmap, w, h, boolean color); */ //======================================================Очистка дисплея void Clear_LCD() { for (int index = 0; index < 864 ; index++){ LCD_RAM[index] = (0x00); } } //=====================================================Обновить дисплей void Update(){ for(byte p = 0; p < 9; p++){ SendByte(LCD_C, SetYAddr| p); SendByte(LCD_C, SetXAddr4); SendByte(LCD_C, SetXAddr3); for(byte col=0; col < LCD_X; col++){ SendByte(LCD_D, LCD_RAM[(LCD_X * p) + col]); } } } //======================================================Заливка экрана void fillScreen(boolean color) { fillRect(0, 0, LCD_X, LCD_Y, color); } //===================================================Нарисовать пиксель void drawPixel (byte x, byte y, boolean color) { if ((x < 0) || (x >= LCD_X) || (y < 0) || (y >= LCD_Y)) return; if (color) LCD_RAM[x+ (y/8)*LCD_X] |= _BV(y%8); else LCD_RAM[x+ (y/8)*LCD_X] &= ~_BV(y%8); } //=====================================================Нарисовать букву void drawChar(byte x, byte y, boolean color, unsigned char c) { if((x >= LCD_X) ||(y >= LCD_Y) || ((x + 4) < 0) || ((y + 7) < 0)) return; if(c<128) c = c-32; if(c>=144 && c<=175) c = c-48; if(c>=128 && c<=143) c = c+16; if(c>=176 && c<=191) c = c-48; if(c>191) return; for (byte i=0; i<6; i++ ) { byte line; (i == 5)? line = 0x0 : line = pgm(font+(c*5)+i); for (byte j = 0; j<8; j++) { (line & 0x1)? drawPixel(x+i, y+j, color) : drawPixel(x+i, y+j, !color); line >>= 1; } } } //========================================================Вывод строки void drawString(byte x, byte y, boolean color, char *str){ unsigned char type = *str; if(type>=128) x=x-3; while(*str){ drawChar(x, y, color, *str++); unsigned char type = *str; (type>=128)? x=x+3 : x=x+6; } } //====================================================Рисование линии void drawLine(byte x0, byte y0, byte x1, byte y1, boolean color) { int steep = abs(y1 - y0) > abs(x1 - x0); if (steep) { swap(x0, y0); swap(x1, y1); } if (x0 > x1) { swap(x0, x1); swap(y0, y1); } int dx, dy; dx = x1 - x0; dy = abs(y1 - y0); int err = dx / 2; int ystep; (y0 < y1)? ystep = 1 : ystep = -1; for (; x0<=x1; x0++) { (steep)? drawPixel(y0, x0, color) : drawPixel(x0, y0, color); err -= dy; if (err < 0) { y0 += ystep; err += dx; } } } //========================================Рисование вертикальной линии void drawFastVLine(byte x, byte y, byte h, boolean color) { drawLine(x, y, x, y+h-1, color); } //======================================Рисование горизонтальной линии void drawFastHLine(byte x, byte y, byte w, boolean color) { drawLine(x, y, x+w-1, y, color); } //============================================Рисование прямоугольника void drawRect(byte x, byte y, byte w, byte h, boolean color) { drawFastHLine(x, y, w, color); drawFastHLine(x, y+h-1, w, color); drawFastVLine(x, y, h, color); drawFastVLine(x+w-1, y, h, color); } void drawCircle(byte x0, byte y0, int16_t r, boolean color) { int f = 1 - r; int ddF_x = 1; int ddF_y = -2 * r; int x = 0; int y = r; drawPixel(x0, y0+r, color); drawPixel(x0, y0-r, color); drawPixel(x0+r, y0, color); drawPixel(x0-r, y0, color); while (x<y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x; drawPixel(x0 + x, y0 + y, color); drawPixel(x0 - x, y0 + y, color); drawPixel(x0 + x, y0 - y, color); drawPixel(x0 - x, y0 - y, color); drawPixel(x0 + y, y0 + x, color); drawPixel(x0 - y, y0 + x, color); drawPixel(x0 + y, y0 - x, color); drawPixel(x0 - y, y0 - x, color); } } //===============================Рисование скругленного прямоугольника void drawRoundRect(byte x, byte y, byte w, byte h, byte r, boolean color) { // smarter version drawFastHLine(x+r , y , w-2*r, color); // Top drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom drawFastVLine( x , y+r , h-2*r, color); // Left drawFastVLine( x+w-1, y+r , h-2*r, color); // Right // draw four corners drawCircleHelper(x+r , y+r , r, 1, color); drawCircleHelper(x+w-r-1, y+r , r, 2, color); drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color); drawCircleHelper(x+r , y+h-r-1, r, 8, color); } //==============================================Рисование треугольника void drawTriangle(byte x0, byte y0, byte x1, byte y1, byte x2, byte y2, boolean color) { drawLine(x0, y0, x1, y1, color); drawLine(x1, y1, x2, y2, color); drawLine(x2, y2, x0, y0, color); } //======================================================Рисование дуги void drawCircleHelper(byte x0, byte y0, byte r, byte cornername, boolean color) { int f = 1 - r; int ddF_x = 1; int ddF_y = -2 * r; int x = 0; int y = r; while (x<y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x; if (cornername & 0x4) { drawPixel(x0 + x, y0 + y, color); drawPixel(x0 + y, y0 + x, color); } if (cornername & 0x2) { drawPixel(x0 + x, y0 - y, color); drawPixel(x0 + y, y0 - x, color); } if (cornername & 0x8) { drawPixel(x0 - y, y0 + x, color); drawPixel(x0 - x, y0 + y, color); } if (cornername & 0x1) { drawPixel(x0 - y, y0 - x, color); drawPixel(x0 - x, y0 - y, color); } } } //========================================Рисование залитой окружности void fillCircle(byte x0, byte y0, byte r, boolean color) { drawFastVLine(x0, y0-r, 2*r+1, color); fillCircleHelper(x0, y0, r, 3, 0, color); } //======================================================Рисование дуги void fillCircleHelper(byte x0, byte y0, byte r, byte cornername, byte delta, boolean color) { int f = 1 - r; int ddF_x = 1; int ddF_y = -2 * r; int x = 0; int y = r; while (x<y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x; if (cornername & 0x1) { drawFastVLine(x0+x, y0-y, 2*y+1+delta, color); drawFastVLine(x0+y, y0-x, 2*x+1+delta, color); } if (cornername & 0x2) { drawFastVLine(x0-x, y0-y, 2*y+1+delta, color); drawFastVLine(x0-y, y0-x, 2*x+1+delta, color); } } } //=====================================Рисование залитый прямоугольник void fillRect(byte x, byte y, byte w, byte h, boolean color) { for (int16_t i=x; i<x+w; i++) { drawFastVLine(i, y, h, color); } } //======================Рисование залитого скругленного прямоугольника void fillRoundRect(byte x, byte y, byte w, byte h, byte r, boolean color) { // smarter version fillRect(x+r, y, w-2*r, h, color); // draw four corners fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color); fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color); } //=====================================Рисование залитого треугольника void fillTriangle(byte x0, byte y0, byte x1, byte y1, byte x2, byte y2, boolean color) { int a, b, y, last; // Sort coordinates by Y order (y2 >= y1 >= y0) if (y0 > y1) { swap(y0, y1); swap(x0, x1); } if (y1 > y2) { swap(y2, y1); swap(x2, x1); } if (y0 > y1) { swap(y0, y1); swap(x0, x1); } if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing a = b = x0; if(x1 < a) a = x1; else if(x1 > b) b = x1; if(x2 < a) a = x2; else if(x2 > b) b = x2; drawFastHLine(a, y0, b-a+1, color); return; } int16_t dx01 = x1 - x0, dy01 = y1 - y0, dx02 = x2 - x0, dy02 = y2 - y0, dx12 = x2 - x1, dy12 = y2 - y1, sa = 0, sb = 0; if(y1 == y2) last = y1; // Include y1 scanline else last = y1-1; // Skip it for(y=y0; y<=last; y++) { a = x0 + sa / dy01; b = x0 + sb / dy02; sa += dx01; sb += dx02; /* longhand: a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); */ if(a > b) swap(a,b); drawFastHLine(a, y, b-a+1, color); } sa = dx12 * (y - y1); sb = dx02 * (y - y0); for(; y<=y2; y++) { a = x1 + sa / dy12; b = x0 + sb / dy02; sa += dx12; sb += dx02; /* longhand: a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); */ if(a > b) swap(a,b); drawFastHLine(a, y, b-a+1, color); } } //======================================================Вывод картинки void drawBitmap(byte x, byte y, const char *bitmap, byte w, byte h, boolean color) { for (int16_t j=0; j<h; j++) { for (int16_t i=0; i<w; i++ ) { if (pgm(bitmap + i + (j/8)*w) & _BV(j%8)) { drawPixel(x+i, y+j, color); } } } } //======================================================================== // Управление дисплеем //======================================================================== //=======================================================Управление пинами void dWrite(byte pin, byte val){ byte bit = digitalPinToBitMask(pin); volatile byte *out; out = portOutputRegister(digitalPinToPort(pin)); (val)? *out |= bit : *out &=~bit; } //=========================================================Отправка 9 байт void SendByte(byte mode, byte c){ dWrite(CS, 0); (mode)? dWrite(Data,1) : dWrite(Data,0); dWrite(Clock, 1); for(byte i=0;i<8;i++){ dWrite(Clock,0); (c & 0x80)? dWrite(Data,1) : dWrite(Data,0); dWrite(Clock,1); c <<= 1; } dWrite(Clock, 0); } //===================================================Инициализация дисплея void Inicialize(){ pinMode(CS, OUTPUT); pinMode(Data, OUTPUT); pinMode(Clock, OUTPUT); // Инициализация дисплея dWrite(Clock, 0); dWrite(Data, 0); dWrite(CS, 0); delay(20); dWrite(CS, 1); SendByte(LCD_C,0x2F); // Power control set(charge pump on/off) SendByte(LCD_C,0xA4); SendByte(LCD_C,0xAF); // экран вкл/выкл Clear_LCD(); Update(); } //=========================Вывод символа 16х32 пикселя в координаты XY void simb16x32(byte x, byte y, boolean color, byte c){ for (byte k=0;k<4;k++){ for (byte i=0;i<16;i++){ byte line = pgm(&(mass16x32[c][i+k*16])); for (byte j = 0; j<8; j++) { (line & 0x01)? drawPixel(x+i, y+j+k*8, color) : drawPixel(x+i, y+j+k*8, !color); line >>= 1; } } } } //=========================Вывод символа 10х16 пикселя в координаты XY void simb10x16(byte x, byte y, boolean color, byte c){ for (byte k=0;k<2;k++){ for (byte i=0;i<10;i++){ byte line = pgm(&(mass10x16[c][i+k*10])); for (byte j = 0; j<8; j++) { (line & 0x01)? drawPixel(x+i, y+j+k*8, color) : drawPixel(x+i, y+j+k*8, !color); line >>= 1; } } } }LDM
//======================================================================== // Главный экран //======================================================================== void Window_0(){ fillScreen(!color); vyvod(skorost); drawRect(S, S, W, H, color); drawRect(S, 12, W, 44, color); drawFastVLine(48, 2, 11, color); drawFastVLine(48, 56, 11, color); drawBitmap(68,33, image, 24, 16, color); drawString(13, 57, color, "Меню"); drawString(55, 57, color, "Данные"); int_LCD(58, 3, middle); if(DATA[0]!=0){ for(byte i=0;i<=n;i++){ fillRect(5+i*4, 3, 3, 8, color); } } Update(); } //======================================================================== // Экран статистики //======================================================================== void Window_1(){ fillScreen(!color); drawRect(S, 5, W, 62, color); drawFastVLine(48, 5, 62, color); for(byte i=15;i<56;i+=10){ drawFastHLine(S, i, W, color); } for(byte i=0;i<10;i++){ if((i==0||i==2||i==4||i==6||i==8)&& DATA[i]!=0){ int_LCD(12, 7+i*5, DATA[i]); } if((i==1||i==3||i==5||i==7||i==9)&& DATA[i]!=0){ int_LCD(58, 7+(i-1)*5, DATA[i]); } } drawString(10, 57, color, "Назад"); drawString(57, 57, color, "Сброс"); Update(); } //======================================================================== // Экран настроек //======================================================================== void Window_2(byte i){ fillScreen(!color); byte n=1; n=n<<i; Menu( 1, myStrings[0], n&1); Menu( 12, myStrings[1], n&2); if(energi) Menu( 23, myStrings[3], n&4); else Menu( 23, myStrings[2], n&4); Menu( 33, myStrings[4], n&8); Menu( 44, myStrings[5], n&16); Update(); } //======================================================================== // Экран калиброки //======================================================================== void Window_3(byte i){ fillScreen(!color); byte n=1; n=n<<i; Menu( 32, myStrings[6], n&1); Menu( 43, myStrings[7], n&2); Menu( 54, myStrings[5], n&4); vyvod_16(calibration); drawString(70, 16, color, "мм"); Update(); } //======================================================================== // Экран настроек массы //======================================================================== void Window_4(byte i){ fillScreen(!color); byte n=1; n=n<<i; Menu( 32, myStrings[6], n&1); Menu( 43, myStrings[7], n&2); Menu( 54, myStrings[5], n&4); vyvod_16(mass); drawString(70, 16, color, "гр."); Update(); } //======================================================================== // Вывод скорости статистики и средней //======================================================================== void int_LCD(byte x, byte y, int temp){ char c4=char(48+temp%10); temp/=10; char c3=char(48+temp%10); temp/=10; char c2=char(48+temp%10); temp/=10; char c1=char(48+temp%10); drawChar(x, y, color, c1); drawChar(x+6, y, color, c2); drawChar(x+12, y, color, c3); drawChar(x+17, y, color, '.'); drawChar(x+21, y, color, c4); } //======================================================================== // Вывод строки меню //======================================================================== void Menu(byte y, char *str, boolean tap){ byte h=12; byte length=strlen(str); unsigned char AN_RU = *str; if(AN_RU>128) length=length/2; if(tap){ fillRect(2, y, LCD_X-4, h, color); drawString(LCD_X/2-length*3+2, y+2, !color, str); } else{ fillRect(2, y, LCD_X-4, h, !color); drawString(LCD_X/2-length*3+2, y+2, color, str); } } //======================================================================== // Вывод текущей скорости //======================================================================== void vyvod(int skor){ unsigned int temp=skor; // переменная для хранения unsigned int c4=temp%10; // четвертая цифра скорости temp/=10; unsigned int c3=temp%10; // третья цифра скорости temp/=10; unsigned int c2=temp%10; // вторая цифра скорости temp/=10; unsigned int c1=temp%10; // первая цифра скорости simb16x32(9, 17, color, c1); simb16x32(29, 17, color, c2); simb16x32(49, 17, color, c3); simb10x16(75, 17, color, c4); } //======================================================================== // Вывод цифр 10х16 //======================================================================== void vyvod_16(byte n){ byte temp=n; byte c3=temp%10; temp/=10; byte c2=temp%10; temp/=10; byte c1=temp%10; if(c1==0){ simb10x16(38, 8, color, c2); simb10x16(51, 8, color, c3); if(display_N==4) drawRect(48, 24, 3, 2, color); } else{ simb10x16(30, 8, color, c1); simb10x16(43, 8, color, c2); simb10x16(56, 8, color, c3); if(display_N==4) drawRect(53, 24, 3, 2, color); } }Main
void setup(){ attachInterrupt(0, Start, RISING); //Прерывание по нарастающему фронту на D0 attachInterrupt(1, End, RISING); //Прерывание по нарастающему фронту на D1 Inicialize(); pinMode(pin_1, INPUT_PULLUP); pinMode(pin_2, INPUT_PULLUP); if(EEPROM.read(adr_first)==0){ EEPROM.write(adr_first, 100); EEPROM.write(adr_calibr, 100); EEPROM.write(adr_energi, 0); EEPROM.write(adr_mass , 100); EEPROM.write(adr_color, 0); EEPROM.write(adr_safe, 100); } calibration=EEPROM.read(adr_calibr); mass= EEPROM.read(adr_mass); energi= EEPROM.read(adr_energi); color= EEPROM.read(adr_color); if(calibration==255) calibration=100; if(mass==255) mass=50; if(energi==255) energi=0; if(color==255) color=1; Window_0(); } void loop(){ if(!test) spped(); //======================================================================== // Тестирование датчиков //======================================================================== if(digitalRead(pin_1)==0 && digitalRead(pin_2)==0){ delay(100); if(digitalRead(pin_1)==0 && digitalRead(pin_2)==0){ test=1; } } //======================================================================== // Управление первой кнопкой //======================================================================== if(digitalRead(pin_1)==0 && digitalRead(pin_2)==1){ delay(50); if(digitalRead(pin_1)==0 && digitalRead(pin_2)==1){ test=0; switch (display_N) { case 0: // если главный экран display_N=2; Window_2(display_2_menu); delay(200); break; case 1: // если экран статистики display_N=0; Window_0(); delay(200); break; case 2: // если меню настроек display_2_menu++; if(display_2_menu==5) display_2_menu=0; Window_2(display_2_menu); delay(200); break; case 3: // если экран калибровки display_3_menu++; if(display_3_menu==3) display_3_menu=0; Window_3(display_3_menu); delay(200); break; case 4: // если настройка масса display_4_menu++; if(display_4_menu==3) display_4_menu=0; Window_4(display_4_menu); delay(200); break; } } } //======================================================================== // Управление второй кнопкой //======================================================================== if(digitalRead(pin_2)==0 && digitalRead(pin_1)==1){ delay(50); if(digitalRead(pin_2)==0 && digitalRead(pin_1)==1){ test=0; switch (display_N) { case 0: first(); break; case 1: Stat(); break; case 2: Settints(); break; case 3: Calibr(); break; case 4: massa(); break; } } } if(test) Test(); } //======================================================================== // Главный экран //======================================================================== void first(){ display_N=1; Window_1(); } //======================================================================== // Экран статистики //======================================================================== void Stat(){ for(byte i=0;i<10;i++){ DATA [i]=0; } middle=0; Window_1(); } //======================================================================== // Экран настроек //======================================================================== void Settints(){ switch (display_2_menu) { case 0: // переходим в калибровку display_N=3; Window_3(display_3_menu); delay(200); break; case 1: // Настройка массы display_N=4; Window_4(display_4_menu); delay(200); break; case 2: // Скорость/энергия energi=!energi; EEPROM.write(adr_energi, energi); Window_2(display_2_menu); break; case 3: // Инвертирование color=!color; EEPROM.write(adr_color, color); Window_2(display_2_menu); break; case 4: // Назад display_N=0; display_2_menu=0; Window_0(); delay(200); break; } } //======================================================================== // Экран калибровки //======================================================================== void Calibr(){ switch (display_3_menu) { case 0: if(calibration<254) calibration++; Window_3(display_3_menu); break; case 1: if(calibration>0) calibration--; Window_3(display_3_menu); break; case 2: display_N=2; Window_2(display_2_menu); display_3_menu=0; delay(200); EEPROM.write(adr_calibr, calibration); break; } } //======================================================================== // Управление массой //======================================================================== void massa(){ switch (display_4_menu) { case 0: if(mass<250) mass++; Window_4(display_4_menu); break; case 1: if(mass>0) mass--; Window_4(display_4_menu); break; case 2: display_N=2; Window_2(display_2_menu); display_4_menu=0; delay(200); EEPROM.write(adr_mass, mass); break; } } //======================================================================== // Рассчет текущей и средней скорости //======================================================================== void spped(){ if (flag1==0 && flag2==0){ skorost = calibration*factor/(time2-time1); //вычисляем скорость для расстояния между датчиками 7см if(DATA[0]==0) { n=0; DATA[n]=skorost; } else { n++; if(n>9){ for(byte i=0;i<9;i++){ DATA[i]=DATA[i+1]; } n=9; } DATA[n]=skorost; } for(byte i=0;i<n;i++){ middle=middle+DATA[i]; } if(n!=0) middle=middle/(n+1); Window_0(); delay(100); time2=0; flag1 = 1; flag2 = 1; } } //======================================================================== // Проверка датчиков //======================================================================== void Test(){ fillScreen(!color); drawRect(10, 25, 75, 15, color); fillRect(13, 20, 11, 5, color); fillRect(71, 20, 11, 5, color); fillRect(13, 40, 11, 5, color); fillRect(71, 40, 11, 5, color); fillTriangle(75, 55, 65, 50, 65, 60, color); fillRect(20, 53, 45, 4, color); drawString(9, 3, color, "Тест датчиков"); if(flag1==0) fillCircle(18, 32, 4, color); if(flag2==0) fillCircle(76, 32, 4, color); if((micros()-time1) >500000) flag1=1; if((micros()-time2) >500000) flag2=1; for(byte i=0;i<10;i++){ DATA [i]=0; } middle=0; Update(); }Всего 1242 строки кода, половина это символы, переменные и графические функции
Благодрю,попробую вытащить нужное.
Хотелось бы посмотреть на финальную схему.
да какая там схема. мега8 кварц несколько резисторов и пребразователь со стабилизатором. ну и в датчиках ик диоды и фототранзисторы
ок, буду смотреть на разводку платы.
А почему экран выбрали именно 1202, а не 5110 под который есть куча либ? Неужели пикселей нехватило?
1202 96x68 pix.
5110 84x48 pix.
потому что он мне нравится)))
Есть у кого вариант датчика для огнестрелов ?
Здравсвуйте.
Я пока собрал в виде макета на arduino pro micro (ATmega32U4), залил скетч выложенный здесь. Пока полазил по менушке и вроде все отлично, но есть пару вопросов.
1.Когда переходиш по пунктам меню, то в момент перехода с пункта на пункт промаргивает не однородно закрашенный черный экран. Так у всех или только у меня?
2. В программе хорошо видно, какие выводы управляют экраном, а какие кнопками и их можно переназначить. А где в программе видно, что именно выводы 2 и 3 отвечают за обработку фототранзисторов и можно ли их переназначить на другие выводы?.
привет
1. не видел такого
2. выводы можно поменять кроме фототранзисторов.
2 и 3 пины это прерывания: в файле main 2 и 3 строка
посмотрел немного свой код, нашел ряд не очень оптимальных решений. например в функцию отрисовки экрана не обязательно передавать пункт меню, смысла нет, так как переменная все равно глобальная.
можно ускорить отрисовку экрана. поменять функцию SendByte на эту:
//=========================================================Отправка 9 байт void SendByte(byte mode, byte c){ dWrite(CS, 0); (mode)? dWrite(Data,1) : dWrite(Data,0); dWrite(Clock, 1); for(byte i=0;i<8;i++){ dWrite(Clock,0); (c & 0x80)? dWrite(Data,1) : dWrite(Data,0); dWrite(Clock,1); c <<= 1; } dWrite(Clock, 0); }если еще покопаться можно еще что нибудь оптимизировать
Уважаемый jeka_tm.
Не знаю интересна вам еще эта тема или нет, но вы как то спрашивали в этом форуме предложения по отрисовке уровня заряда батареи. Так вот если еще интересно, то уровень заряда можно отображать просто в процентах от 0% до 100% в окне количества измерений.
уровень заряда я уже далал как то. и вроде неплохо получилось, только графически делал
А можно выложить код обработки и отрисовки уровня заряда батареи, как это реализовано у вас тут?
там его нет. это количество измерений
видео нашел. код не помню выкладывал или нет
http://www.youtube.com/watch?v=bhSiFH5RnLM
Кажатся нашел, я так понимаю этот код считывает и отображает уровень заряда
//считаем напряжение void napr(){ U = analogRead(accum); U = constrain(U, 547, 614); U = map(U, 547, 614, 0, 9); Goto_XY(80,0); for (int i = 0; i<3; i++){ SendByte(1,pgm_read_byte(&(batt[i]))); } if (U == 9){ for (int i = 0; i<9; i++){ SendByte(1,pgm_read_byte(&(batt[3]))); } } if (U<9){ for (int i = 0; i<(9-U); i++){ SendByte(1,pgm_read_byte(&(batt[2]))); } for (int i = 0; i<U; i++){ SendByte(1,pgm_read_byte(&(batt[3]))); } } SendByte(1,pgm_read_byte(&(batt[2]))); SendByte(1,pgm_read_byte(&(batt[1]))); }ага. только это для питания 5В. у меня питалось от аккумулятора через преобразователь на 5В
Так и я хочу Li-ion аккумулятор запитать через Step-UP преобразователь. Только буду мерять напряжение на самом аккумуляторе (от 3в до 4,2В), а иначе смысл мерить постоянно 5В.
А вы запитывали через делитель или напрямую?
Да и как вы получили значения 547 и 614 ?
напрямую. конечно на самом аккумуляторе. значение получил опытным путем. это 2 порога которые выбрал: 3 и 4.2В. вроде так
Это понятно что опытным путем, меняете напряжение на входе и видите, что видит АЦП в цифрах. Не с потолка же взяли эти числа ))) Я пока просто учусь. Вот и думаю как посмотреть что видит АЦП в реальном времени и ест ли такие средства у ардуины? Или я не правильно понял принцип?
Все нашел как
//добавил в вкладке Speed_v5.9.8.ino //считаем напряжение #define accum A0 int U = 0; int a = 0; void battary() { U = analogRead(accum); U = constrain(U, 650, 855); U = map(U, 650, 855, 0, 9); for( a=0;a<=U;a++) fillRect(5+a*4, 3, 3, 8, color); }// изменил во вкладке LDM //======================================================================== // Главный экран //======================================================================== void Window_0(){ fillScreen(!color); vyvod(skorost); drawRect(S, S, W, H, color); drawRect(S, 12, W, 44, color); drawFastVLine(48, 2, 11, color); drawFastVLine(48, 56, 11, color); drawBitmap(68,33, image, 24, 16, color); drawString(13, 57, color, "Меню"); drawString(55, 57, color, "Данные"); int_LCD(58, 3, middle); /* if(DATA[0]!=0){ for(byte i=0;i<=n;i++){ fillRect(5+i*4, 3, 3, 8, color); } } */ battary(); Update(); }да все просто
в конце loop добавить после :
эту строку
фото или видео не забудь приложить что получилось