Ви не увійшли.
Сторінки 1
Можно к ошейнику приделать цепь такой длины, чтобы он не дотягивался до стенки. Шучу. Можно возле стенки в том месте временно поставить какой-то щит. Можно еще испытать временное средство (сам не пробовал) - говорят, что кошки не любят прикасаться ко всяким липким штукам - повесить временно перед стенкой ленты широкого скотча на натянутой леске... У самого везде коты кошки, поэтому уже смирился - пусть дерет! )
У меня тут на ночь глядя перед глазами страшные картины - кот, обвешанный аккумуляторами и ардуино подходит к стене, а управляемый ардуино молоток из коробочки на спине кота, бьет его по голове. Кот в наушниках, и подходя к стене, у него играет нелюбимая музыка...
Наверно, чтобы не мучать кота, можно попробовать просто на ИК фотодатчике сделать на пути к стене излучатель и приемник, и при срабатывании ардуино громко пищало бы. Я на работе под большим офисным принтером поставил, было дело, ардуино с ультразвуковым датчиком препятствий(http://myshop.biz.ua/index.php?route=in … news_id=15) , когда человек подходил, из-под принтера раздавалась сирена, в общем на людей неплохо работало, чем коты хуже?
Порт появляется в системе, когда Windows обнаружило устройство, подключенное к USB порту, (в данном случае - Arduino), считало идентификатор этого устройства и нашло драйверы, соответствующие этому идентификатору. Поэтому нужно лезть в Диспетчер устройств из "управления компьютером" и смотреть, что там изменяется при подключении Ардуино. Если Ардуина не сгоревшая, если целый кабель, но нет драйверов, соответствующих идентификатору Arduino Mega, то приподключении должно появляться в списке устройств "Неизвестное устройство", если ничего не появляется, скорее всего, плохой контакт/USB кабель/Ардуино. Если драйверы есть, то при подключении Ардуино в Диспетчере устройств будет появляться новый порт, можно раскрыть секцию Com Порты и вставлять/вынимать кабель Ардуино, чтобы видеть - меняется ли что в диспетчере.
Возможно порт и появляется, но чтобы успешно загрузить скетч, в Arduino IDE важно правильно выбрать номер порта, который появлялся пи подключении Ардуино, и обязательно там же нужно выбрать вид платы - Arduino Mega, если там стоит Arduino Nano, то загрузки скорее всего не получится.
Чтобы много не гадать для начало надо объяснить, что происходит в диспетчере задач...
Собрал себе из Ардуино и LCD экрана от телефона Nokia 3310 простенький осциллограф, который оказался очень удобным и простым в эксплуатации. При помощи его можно измерять частоту, изучать форму сигналов, мерять напряжение до 5В (например, проверять батарейки). Есть встроенный генератор сигналов разной формы, терминальный дисплей. Нашел описание этого устройства в интернете, и решил сам его собрать. Тем более, мой старый советский осциллограф сказал "Бам, бубух", и перестал работать (взорвались конденсаторы повышения напряжения). Автор называет устройство "Пультоскоп", поскольку собрал его в пульте дистанционного управления. В конце статьи будут ссылки на автора.
Умеет устройство также работать в качестве монитора последовательного порта - на разъем выведен сигнал Rx Arduino, при переводе в режим "Терминал" устройство "слушает" входной сигнал на частоте 9600 бод. Удобно проверять, если вторая плата ардуино выводит отладочные сообщения в последовательный порт, подключить к выходу этот осциллограф и на экране смотреть выводимые отладочные сообщения.
При минимуме электронных компонентов - польза от устройства неоценимая.
Для сборки потребовалось:
1. Коробочка
2. Arduino Nano
4. Аккумулятор с китайской мобилки
5. Совсем немного резисторов, проводов, разъемов, дремель для проделки дырок в корпусе и др. мелочевка.
6. Экран от телефона Nokia 3310
7. Терпение
Схема устройства:
Вот как выглядит получившееся устройство:
Поскольку я взял оригинальный экран от телефона NOKIA, а не готовый дисплейный модуль, пришлось городить колхоз по его подключению:
На картинке ниже подписал основные компоненты:
Видео работы - для демонстрации я на второй платке Arduino запустил программу Fade, которая на 9-м пине занимается ШИМ (широтно-импульсной модуляцией), на видео можно таки рассмотреть, как ШИМ выглядит.:
Поскольку я не являюсь автором идеи, не стал делать слишком подробное описание, все в избытке можно найти на странице автора и в форумах, публикую, чтобы привлечь внимание к такой интересной разработке - наверное, не все еще видели в интернете.
Текст программы, который использовал я:
//Страница проэкта http://srukami.inf.ua/pultoscop_v25110.html
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#include <FreqCount.h>
#include <SPI.h>
#include <PWM.h>
#include <CyberLib.h>
#define led 6 //пин для генератора сигналов (не менять)
#define dds 7 //пин для генератора dds (не менять)
//#################№№№№№№####пользовательские настройки
#define power 8 //пин который опрашивает кнопку включения
#define OFF 14//пин который управляет ключем питания
#define timepowerON 50 //время удержания кнопки выключения
#define levo 2 //кнопка ЛЕВО(можно любой пин)
#define ok 3 //кнопка ОК(можно любой пин)
#define pravo 4 //кнопка ПРАВО(можно любой пин)
#define akb A6 //любой своюодный аналоговый пин для измерения напряжения АКБ
#define overclock 16 //Частота на которой работает Ардуино
Adafruit_PCD8544 display = Adafruit_PCD8544(14, 13, 12, 11, 10);//пины к которым у вас подключен дисплей
byte cont=52;//контрастность дисплея
byte SinU=30; //уровень синхронизации 0 до 255
int PWM = 128;//стартовое значение ШИМ от 0 до 255
int32_t frequency = 500; //стартовое значение частоты в Гц
float VCC=5.0; //напряжение питания, меряем мультиметром
//###########################################################
int d=0;
byte menuDDS=0;
byte sinM[32]={1,6,15,29,48,69,92,117,143,168,191,212,229,243,251,255,254,248,237,222,203,181,156,131,106,81,59,39,22,10,3,1};
byte pilaM[32]={1,9,17,25,33,41,49,57,65,73,81,89,97,105,113,121,129,137,145,153,161,169,177,185,193,201,209,217,225,235,245,255};
byte RpilaM[32]={250,246,238,230,222,214,206,198,190,182,174,166,158,150,142,134,126,118,110,102,94,86,78,70,62,54,41,33,25,17,9,1};
byte trianglM[32]={1,18,35,52,69,86,103,120,137,154,171,188,205,222,239,255,239,223,207,191,175,159,143,127,111,95,79,63,47,31,15,1};
int powerON=0;//состояние кнопки питания
byte hag=0;
int mnog=0;
boolean flag=0;
byte mass[701];
byte x=0;
byte menu=0;//переменная выбора меню
bool opornoe=1; //флаг опорного напряжения
bool paus=0; //флаг режима паузы
byte pultoskop=0; //флаг выбора генератора или осциллографа
byte razv=6;
unsigned long count =0;
byte sinX=30;
byte meaX=83;
int Vmax=0;// максимальное напряжение
byte sinhMASS=0;
long countX=0;
long speedTTL=9600; //скорость терминала
int prokr=0;
void setup(){
pinMode(A3,INPUT);
digitalWrite(OFF,HIGH);//включем питание
//Serial.begin(9600);
display.begin();
display.setContrast(cont);
while(digitalRead(ok)==LOW){
/////////////////////////////////////////удержание кнопки отключения
if(digitalRead(power)==HIGH){powerON++;delay(10);}
if(powerON>=timepowerON){digitalWrite(OFF,LOW);}///отключаем питание
/////////////////////////////////////////удержание кнопки отключения
if(pultoskop==0){
display.clearDisplay();
display.setCursor(10,0);
display.setTextColor(WHITE, BLACK); // 'inverted' text
display.println("Pultoscop");
display.setCursor(10,10);
display.setTextColor(BLACK);
display.println("Generator");
display.setCursor(10,20);
display.println("DDSgenerator");
display.setCursor(10,30);
display.println("Terminal");
display.setCursor(0,40);
display.print("Battery=");
display.print(analogRead(akb)*5.0/1024);
display.print("V");
}
if(pultoskop==1){
display.clearDisplay();
display.setCursor(10,0);
display.setTextColor(BLACK); // 'inverted' text
display.println("Pultoscop");
display.setCursor(10,10);
display.setTextColor(WHITE, BLACK); // 'inverted' text
display.println("Generator");
display.setTextColor(BLACK); // 'inverted' text;
display.setCursor(10,20);
display.println("DDSgenerator");
display.setCursor(10,30);
display.println("Terminal");
display.setCursor(0,40);
display.setTextColor(BLACK);
display.print("Battery=");
display.print(analogRead(akb)*5.0/1024);
display.print("V");
}
if(pultoskop==2){
display.clearDisplay();
display.setCursor(10,00);
display.setTextColor(BLACK); // 'inverted' text
display.println("Pultoscop");
display.setCursor(10,10);
display.println("Generator");
display.setTextColor(WHITE, BLACK); // 'inverted' text;
display.setCursor(10,20);
display.println("DDSgenerator");
display.setTextColor(BLACK);
display.setCursor(10,30);
display.println("Terminal");
display.setCursor(0,40);
display.setTextColor(BLACK);
display.print("Battery=");
display.print(analogRead(akb)*5.0/1024);
display.print("V");
}
if(pultoskop==3){
display.clearDisplay();
display.setCursor(10,00);
display.setTextColor(BLACK); // 'inverted' text
display.println("Pultoscop");
display.setCursor(10,10);
display.println("Generator");
display.setTextColor(BLACK);
display.setCursor(10,20);
display.println("DDSgenerator");
display.setTextColor(WHITE, BLACK);
display.setCursor(10,30);
display.println("Terminal");
display.setCursor(0,40);
display.setTextColor(BLACK);
display.print("Battery=");
display.print(analogRead(akb)*5.0/1024);
display.print("V");
}
if(digitalRead(levo)==HIGH){delay(300);pultoskop=pultoskop+1;}
if(digitalRead(pravo)==HIGH){delay(300);pultoskop=pultoskop+1;}
if(pultoskop>3){pultoskop=0;}
delay(50);
display.display(); }
if(pultoskop==2){InitTimersSafe(); bool success = SetPinFrequencySafe(led,200000);}
if(pultoskop==0){FreqCount.begin(1000);}
if(pultoskop==1){InitTimersSafe(); bool success = SetPinFrequencySafe(led, frequency);}
display.setTextColor(BLACK);
delay(500); }
void Zamer(){
if (razv>=6){ADCSRA = 0b11100010;}//delitel 4
if (razv==5){ADCSRA = 0b11100011;}//delitel 8
if (razv==4){ADCSRA = 0b11100100;}//delitel 16
if (razv==3){ADCSRA = 0b11100101;}//delitel 32
if (razv==2){ADCSRA = 0b11100110;}//delitel 64
if (razv<2){ADCSRA = 0b11100111;}//delitel 128
if (razv==0){
for(int i=0;i<700;i++){
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
delayMicroseconds(500);
mass[i]=ADCH;
}
}
if (razv>0){
for(int i=0;i<700;i++){
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
mass[i]=ADCH;
}
}
}
void loop() {
/////////////////////////////////////////удержание кнопки отключения
if(digitalRead(power)==HIGH){powerON++;delay(10);}
if(powerON>=timepowerON){digitalWrite(OFF,LOW);}///отключаем питание
/////////////////////////////////////////удержание кнопки отключения
if(pultoskop==0){
if(opornoe==0){ADMUX = 0b11100011;}//выбор внутреннего опорного 1,1В
if(opornoe==1){ADMUX = 0b01100011;}//Выбор внешнего опорного
delay(5);
if(paus==0){Zamer();}
//#######################################определение точки синхронизации
bool flagSINHRO=0;
bool flagSINHRnull=0;
for(int y=1;y<255;y++){
if(flagSINHRO==0){if(mass[y]<SinU){flagSINHRnull=1;}}
if(flagSINHRO==0){if(flagSINHRnull==1){if(mass[y]>SinU){flagSINHRO=1;sinhMASS=y;}}}}
//#######################################определение точки синхронизации
//максимальное значение сигнала##########################
Vmax=0;
for(int y=1;y<255;y++){if(Vmax<mass[y]){Vmax=mass[y];} }
//максимальное значение сигнала##########################
//#######################################определение точки синхронизации
//#######################################отрисовка графика
if(paus==0){
display.clearDisplay();
display.fillCircle(80,47-SinU/7, 2, BLACK);//рисуем уровень синхронизации
x=3;
for(int y=sinhMASS;y<sinhMASS+80;y++){
if(razv<7){x++;}
if(razv==7){x=x+2;}
if(razv==8){x=x+3;}
display.drawLine(x, 47-mass[y]/7, x+1, 47-mass[y+1]/7, BLACK);
display.drawLine(x+1, 47-mass[y]/7+1, x+2, 47-mass[y+1]/7+1, BLACK);
}
sinhMASS=0;}
if(paus==1){
display.clearDisplay();
display.drawLine(prokr/8,8,prokr/8+6,8, BLACK);//шкала прокрутки
display.drawLine(prokr/8,9,prokr/8+6,9, BLACK);//шкала прокрутки
x=3;
for(int y=prokr;y<prokr+80;y++){
if(razv<7){x++;}
if(razv==7){x=x+2;}
if(razv==8){x=x+3;}
display.drawLine(x, 47-mass[y]/7, x+1, 47-mass[y+1]/7, BLACK);
display.drawLine(x+1, 47-mass[y]/7+1, x+2, 47-mass[y+1]/7+1, BLACK);
}}
//#######################################отрисовка графика
for(byte i=47;i>5;i=i-7){display.drawPixel(0,i, BLACK);display.drawPixel(1,i, BLACK);display.drawPixel(2,i, BLACK);}//разметка экрана вертикальная
//////////////////////////////////////////////////сетка
for(byte i=47;i>5;i=i-3){display.drawPixel(21,i, BLACK);display.drawPixel(42,i, BLACK);display.drawPixel(63,i, BLACK);}
for(byte i=3;i<84;i=i+3){display.drawPixel(i,33, BLACK);display.drawPixel(i,19, BLACK);}
//////////////////////////////////////////////////сетка
//#######################################отрисовка menu
if(menu==0){
display.setCursor(0,0);
display.setTextColor(WHITE,BLACK);
if(opornoe==0){display.print("1.1");}
if(opornoe==1){display.print(VCC,1);}
display.setTextColor(BLACK);
display.print(" ");
display.print(razv);
display.print(" P");
if(digitalRead(levo)==HIGH){opornoe=!opornoe;}
if(digitalRead(pravo)==HIGH){opornoe=!opornoe;}
}
if(menu==1){
display.setCursor(0,0);
display.setTextColor( BLACK);
if(opornoe==0){display.print("1.1");}
if(opornoe==1){display.print(VCC,1);}
display.setTextColor(WHITE, BLACK); // 'inverted' text
display.print(" ");
display.print(razv);
display.setTextColor( BLACK); // 'inverted' text
display.print(" P");
if(digitalRead(levo)==HIGH){razv=razv-1;if(razv==255){razv=0;}}
if(digitalRead(pravo)==HIGH){razv=razv+1;if(razv==9){razv=8;}}
}
if(menu==2){
display.setCursor(0,0);
display.setTextColor( BLACK);
if(opornoe==0){display.print("1.1");}
if(opornoe==1){display.print(VCC,1);}
display.print(" ");
display.print(razv);
display.setTextColor(WHITE, BLACK); // 'inverted' text
display.print(" P");
paus=1;
if(digitalRead(levo)==HIGH){prokr=prokr-10;if(prokr<0){prokr=0;}}
if(digitalRead(pravo)==HIGH){prokr=prokr+10;if(prokr>620){prokr=620;}}
}
if(menu==3){
prokr=0;
paus=0;
display.setCursor(0,0);
display.setTextColor( BLACK);
if(opornoe==0){display.print("1.1");}
if(opornoe==1){display.print(VCC,1);}
display.print(" ");
display.print(razv);
display.setTextColor(BLACK);
display.print(" P");
if(digitalRead(levo)==HIGH){SinU=SinU-20;if(SinU<20){SinU=20;}}
if(digitalRead(pravo)==HIGH){SinU=SinU+20;if(SinU>230){SinU=230;}}
display.fillCircle(80,47-SinU/7, 5, BLACK);
display.fillCircle(80,47-SinU/7, 2, WHITE);
}
if(digitalRead(ok)==HIGH){menu++;if(menu==4){menu=0;paus=0;}}//перебор меню
if (FreqCount.available()) { count = FreqCount.read();}//вывод частоты по готовности счетчика
//#######################################частоты сигнала
byte Frec1=0;
long Frec=0;
bool flagFrec1=0;
bool flagFrec2=0;
bool flagFrec3=0;
for(int y=1;y<255;y++){
if(flagFrec1==0){if(mass[y]<SinU){flagFrec2=1;}}
if(flagFrec1==0){if(flagFrec2==1){if(mass[y]>SinU){flagFrec1=1;Frec1=y;}}}
if(flagFrec1==1){if(mass[y]<SinU){flagFrec3=1;}}
if(flagFrec3==1){if(mass[y]>SinU){
if (razv>=6){Frec=1000000/((y-Frec1-1)*3.27);}//delitel 4
if (razv==5){Frec=1000000/((y-Frec1)*3.27)/2;}//delitel 8
if (razv==4){Frec=1000000/((y-Frec1)*3.27)/4;}//delitel 16
if (razv==3){Frec=1000000/((y-Frec1)*3.27)/8;}//delitel 32
if (razv==2){Frec=1000000/((y-Frec1)*3.27)/16;}//delitel 64
if (razv==2){Frec=1000000/((y-Frec1)*3.27)/32;}//delitel 128
if (razv==1){Frec=1000000/((y-Frec1)*3.27)/32;}//delitel 128
if (razv==0){Frec=1000000/((y-Frec1)*500);}//delitel 128
flagFrec1=0;flagFrec3=0;}}}
//#######################################частоты сигнала
display.setTextColor( BLACK);
if(opornoe==1){
if((Vmax*VCC/255)>2.5){countX=count*(overclock/16.0);}
if((Vmax*VCC/255)<2.5){countX=Frec*(overclock/16.0);}}
if(opornoe==0){countX=Frec*(overclock/16.0);}
if(countX<1000){display.print(" ");display.print(countX);display.print("Hz");}
if(countX>1000){float countXK=countX/1000.0;display.print(countXK,1);display.print("KHz");}
if(opornoe==1){display.setCursor(0,40);display.setTextColor(BLACK);
display.print(Vmax*VCC/255,1);}
if(opornoe==0){display.setCursor(0,40);display.setTextColor(BLACK);
display.print(Vmax*1.1/255,1);}
display.print("V");
//#######################################отрисовка menu
delay(200);
display.display();
}
if(pultoskop==1){Generator();}
if(pultoskop==2){DDSGenerator();}
if(pultoskop==3){TTL();}
}
//#######################################режим ренератора
void Generator(){
display.clearDisplay();
if (flag==0){//флаг выборов режима настройки ШИМ или Частоты
if(digitalRead(levo)==HIGH){
frequency=frequency-mnog;
if(frequency<0){frequency=0;}
bool success = SetPinFrequencySafe(led, frequency);
delay(3);//защита от дребезга
}
if(digitalRead(pravo)==HIGH){
frequency=frequency+mnog;
bool success = SetPinFrequencySafe(led, frequency);
delay(3);//защита от дребезга
}
}
if (flag==1){//флаг выборов режима настройки ШИМ или Частоты
if(digitalRead(levo)==HIGH){
PWM=PWM-1;
if(PWM<0){PWM=255;}
delay(3);//защита от дребезга
}
if(digitalRead(pravo)==HIGH){
PWM=PWM+1;
if(PWM>255){PWM=0;}
delay(3);//защита от дребезга
}
}
if(digitalRead(ok)==HIGH){//переключение разряда выбора частоты
delay(3);//защита от дребезга
hag++;
if(hag>=5){hag=0;}
}
////////////
display.setTextSize(1);
display.setCursor(0,5);
display.print("PWM=");
display.print(PWM*100.0/255);
display.print(" %");
display.drawLine(0,0,83*PWM/255.0,0, BLACK);
display.drawLine(0,1,83*PWM/255.0,1, BLACK);
display.drawLine(0,2,83*PWM/255.0,2, BLACK);
display.drawLine(0,15,83*PWM/255.0,15, BLACK);
display.drawLine(0,16,83*PWM/255.0,16, BLACK);
display.drawLine(0,17,83*PWM/255.0,17, BLACK);
///////////
display.setCursor(5,20);
display.setTextSize(2);
long frequencyX=frequency*(overclock/16.0);
if(frequencyX<1000){display.print(frequencyX);display.setTextSize(1);display.println("Hz");}
if(frequencyX>1000){if(frequencyX<10000){display.print((frequencyX/1000.0),2);display.setTextSize(1);display.println("KHz");}}
if(frequencyX>=10000){if(frequencyX<100000){display.print((frequencyX/1000.0),1);display.setTextSize(1);display.println("KHz");}}
if(frequencyX>=100000){display.print((frequencyX/1000.0),0);display.setTextSize(1);display.println("KHz");}
display.setCursor(0,40);
display.setTextSize(1);
display.print(">>X ");
if(hag==0){//выбор множителя частоты
display.print(1*(overclock/16.0),1);
mnog=1;
flag=0;
}
if(hag==1){//выбор множителя частоты
display.print(10*(overclock/16.0),0);
mnog=10;
}
if(hag==2){//выбор множителя частоты
display.print(100*(overclock/16.0),0);
mnog=100;
}
if(hag==3){//выбор множителя частоты
display.print(1000*(overclock/16.0),0);
mnog=1000;
}
if(hag==4){//выбор PWM
display.print("PWM ");
display.print(PWM*100.0/255);
display.print("%");
flag=1;
}
display.print("<<");
pwmWrite(led, PWM);
delay(300);
display.display();
}
/////////////////////DDS
void DDSGenerator(){
int fr=10;
if(menuDDS==0){
display.clearDisplay();
display.setTextColor(WHITE, BLACK); // 'inverted' text
display.setCursor(10,0);
display.println("Sinus");
display.setTextColor(BLACK);
display.setCursor(10,10);
display.println("Triangle");
display.setCursor(10,20);
display.println("Saw");
display.setCursor(10,30);
display.println("Back Saw");
display.setTextColor(BLACK);
display.setCursor(0,40);
//display.print("Частота=");
//display.print(57);
//display.print("Гц");
delay(100);
display.display();
while(D11_Read==LOW){
PWM=sinM[d];
pwmWrite(dds,PWM);
//delayMicroseconds(fr);
d++;
if(d==32){d=0;}}
menuDDS++;
delay(200);}
if(menuDDS==1){
display.clearDisplay();
display.setTextColor(BLACK); // 'inverted' text
display.setCursor(10,0);
display.println("Sinus");
display.setTextColor(WHITE, BLACK);
display.setCursor(10,10);
display.println("Triangle");
display.setTextColor(BLACK);
display.setCursor(10,20);
display.println("Saw");
display.setCursor(10,30);
display.println("Back Saw");
display.setTextColor(BLACK);
//display.setCursor(0,40);
//display.print("Частота=");
// display.print(57);
//display.print("Гц");
delay(100);
display.display();
while(D11_Read==LOW){
PWM=trianglM[d];
pwmWrite(dds,PWM);
//delayMicroseconds(fr);
d++;
if(d==32){d=0;}}
menuDDS++;
delay(200);}
if(menuDDS==2){
display.clearDisplay();
display.setTextColor(BLACK); // 'inverted' text
display.setCursor(10,0);
display.println("Sinus");
display.setTextColor(BLACK);
display.setCursor(10,10);
display.println("Triangle");
display.setTextColor(WHITE, BLACK);
display.setCursor(10,20);
display.println("Saw");
display.setTextColor(BLACK);
display.setCursor(10,30);
display.println("Back Saw");
display.setTextColor(BLACK);
//display.setCursor(0,40);
//display.print("Частота=");
// display.print(57);
//display.print("Гц");
delay(100);
display.display();
while(D11_Read==LOW){
PWM=pilaM[d];
pwmWrite(dds,PWM);
// delayMicroseconds(fr);
d++;
if(d==32){d=0;}}
menuDDS++;
delay(200);}
if(menuDDS==3){
display.clearDisplay();
display.setTextColor(BLACK); // 'inverted' text
display.setCursor(10,0);
display.println("Sinus");
display.setTextColor(BLACK);
display.setCursor(10,10);
display.println("Triangle");
display.setTextColor(BLACK);
display.setCursor(10,20);
display.println("Saw");
display.setTextColor(WHITE, BLACK);
display.setCursor(10,30);
display.println("Back Saw");
display.setTextColor(BLACK);
//display.setCursor(0,40);
//display.print("Частота=");
// display.print(57);
// display.print("Гц");
delay(100);
display.display();
while(D11_Read==LOW){
PWM=RpilaM[d];
pwmWrite(dds,PWM);
//delayMicroseconds(fr);
d++;
if(d==32){d=0;}}
menuDDS++;
delay(200);}
if(menuDDS==4){menuDDS=0;}
}
/////////////////////DDS
/////////////////////TTL
void TTL(){
display.clearDisplay();
display.setTextColor(BLACK);
display.setCursor(10,0);
display.println("Terminal");
display.setCursor(10,10);
display.println("Speed");
display.setCursor(10,20);
display.print("-");
display.print(speedTTL);
display.println("+");
display.setCursor(0,30);
display.println("Press OK-start");
if(digitalRead(pravo)==HIGH){speedTTL=speedTTL+100;}
if(digitalRead(levo)==HIGH){speedTTL=speedTTL-100;}
if(speedTTL<0){speedTTL=250000;}
if(speedTTL>250000){speedTTL=0;}
if(digitalRead(ok)==HIGH){Serial.begin(speedTTL*(16/overclock));
display.clearDisplay();
delay(100);
display.display();
int x=0;
int y=0;
while(1){
char incomingBytes;
if (Serial.available() > 0) { // Если в буфере есть данные
incomingBytes=Serial.read(); // Считывание байта в переменную incomeByte
display.setCursor(x,y);
display.print(incomingBytes); // Печать строки в буффер дисплея
display.display(); x=x+6;
if(x==84){x=0;y=y+8;}
if(y==48){x=0;y=0;
display.clearDisplay();
delay(100);
display.display();}}
}}
delay(100);
display.display();
}
/////////////////////TTL
Страница разработчика "Пультоскопа": http://srukami.inf.ua/pultoscop_v25110.html
04.12.2016 Дубликат этой страницы
Устройство разработано для обеспечения возможности автоматического включения подсветки аквариума по расписанию, но может использоваться для других целей. Собрано в небольшой коробочке, содержит Arduino Mini Pro 5V 328, модуль реле, и модуль часов реального времени на чипе DS1307. Вместо этого модуля часов, можно без переделки использовать более современный ds3231.
Может включать и выключать нагрузку по заданному в программе расписанию. Реле рассчитано на подключение достаточно мощной нагрузки (250 вольт 10 Ампер), но утюг к нему подключать не следует, поскольку кроме реле, еще нужно учитывать тонкие дорожки на плате. Но, тем не менее, управлять лампами небольшой мощности можно достаточно уверенно. Тем более, что на плате модуля реле предусмотрена оптронная развязка по питанию, т.е Ардуино отделено от высоковольтной части реле.
Миниатюрность Ардуино имеет минус - на такой плате не поместился преобразователь USB в TTL и его приходится подключать к плате снаружи, в корпусе я изготовил пропил, куда вывел разъем гребенку, припаяв его к плате Arduino Mini Pro. На снимке в правом верхнем углу виден припаяный к Ардуино небольшой голубой конденсатор - он используется для организации автоматического ресета при запуске программирования (не нужно нажимать кнопку Reset на Arduino Mini Pro, чтобы инициировать режим программирования). Модуль преобразователя USB 2 UART на чипе cp2102 имеет отдельный вывод DTR, выведенный на разъем, который и обеспечивает сигнал Reset.
Чтобы сделать автоматический Reset для arduino-mini надо прицепить конденсатор 0.1мкф от DTR на вывод reset ардуины (см. даташит на arduino-pro-mini).
Номинал конденсатора не сильно критичен (я ставил 0.68мкф), надо только чтобы RC-цепочка давала импульс не более 1 сек.
Картинка ниже не моя, но отражает ситуацию, резистор подтягивающий RST к VCC я не ставил - и так рабоотает.
Ардуино Mini Pro была выбрана, как самая миниатюрная из имеющихся плат Ардуино, на снимке ниже видно, насколько больше бы потребовалось место для формата Arduino Uno.
Поскольку предполагается запитывать устройство от 12 вольт, в корпусе нашлось место под микросхему стабилизатора на 5 вольт 7805 (Крен 5), которую я прикрепил к радиатору, на всякий случай. Поскольку потребляемый устройством ток небольшой, 7805 и не греется, даже при питании 12 В, когда на ней падает около 7 вольт. На снимке ниже 7805 с радиатором в верхнем левом углу, к ней идут провода питания от модуля часов, реле и Ардуино.
Высокохудожественная схема подключения:
Контакт на плате часов SDA подключаем к контакту A5 платы Ардуино, контакт часов SCL подключаем к выводу A4 Ардуино. На модуле реле два контакта питания (5V И GND), подключаем их на 5 в стабилизатора 7805. Вход управления реле IN подключаем к D10 Arduino.
Установка времени в часы выполняется частью кода, который в скетче сейчас закомментирован. Прописываем нужное время, заливаем в Ардуино, проверяем через монитор последовательного порта, что оно установилось верно, и потом опять комментируем этот участок кода перед повторной заливкой кода рабочей программы управления реле.
Управляется модуль часов по шине I2C, которая стандартно реализована в Ардуино на контактах A4, A5.
Подключение модуля RTC выполняется к аппаратным выводам SDA, и SCL.
RTC модуль часов на базе чипа DS1307 Arduino Mini Pro
GND GND
Vcc +5V
SDA (Serial DAta) A4
SCL (Serial CLock) A5
У модуля реле есть три выхода, схема подключения нагрузки на картинке ниже:
То есть, контакты реле включаются в разрыв цепи нагрузки, как простой переключатель.
#include <Wire.h>
#include "DS1307.h"
DS1307 clock; //define a object of DS1307 class
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin 13 as an output.
pinMode(13, OUTPUT);
pinMode(10, OUTPUT);
Serial.begin(9600);
clock.begin();
// Этот закоментированый кусок кода раскоментируем, когда хотим установить время в часах:
// clock.fillByYMD(2016,11,26);//Jan 19,2013
// clock.fillByHMS(19,48,30);//15:28 30"
// clock.fillDayOfWeek(TUE);//Saturday
// Serial.print("setTime");
printTime();
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
clock.getTime();
// Для примера - включаем реле в 7 часов, выключаем в 10
if (clock.hour==7)
{
digitalWrite(10, HIGH);
Serial.print("On"); Serial.println(clock.minute);
};
if ( clock.hour==10)
{
digitalWrite(10, LOW);
Serial.println("Off");
};
if (clock.hour==19)
{
digitalWrite(10, HIGH);
Serial.print("On"); Serial.println(clock.minute);
};
if ( clock.hour==21)
{
digitalWrite(10, LOW);
Serial.println("Off");
};
}
void printTime()
{
clock.getTime();
Serial.print(clock.hour, DEC);
Serial.print(":");
Serial.print(clock.minute, DEC);
Serial.print(":");
Serial.print(clock.second, DEC);
Serial.print(" ");
Serial.print(clock.month, DEC);
Serial.print("/");
Serial.print(clock.dayOfMonth, DEC);
Serial.print("/");
Serial.print(clock.year+2000, DEC);
Serial.print(" ");
Serial.print(clock.dayOfMonth);
Serial.print("*");
switch (clock.dayOfWeek)// Friendly printout the weekday
{
case MON:
Serial.print("MON");
break;
case TUE:
Serial.print("TUE");
break;
case WED:
Serial.print("WED");
break;
case THU:
Serial.print("THU");
break;
case FRI:
Serial.print("FRI");
break;
case SAT:
Serial.print("SAT");
break;
case SUN:
Serial.print("SUN");
break;
}
Serial.println(" ");
}
Yадо попробовать еще так:
1) Нажать в списке устройств в диспетчере на "Unknown device" которое и является Arduino.
2) Перейти на вкладку этого устройства "Свойства" "Hardware" и выбрать кнопку "Обновить" ("Update Driver").
3) Выбрать вариант "Установка из указанного места" - "Не выполнять поиск" "Я сам укажу, где искать драйвер"..
4) В появившемся списке устройств найты "Порты" ("Ports").
5) Выбрать изготовителя "Arduino LLC" и потом "Arduino UNO". Если в списке производителей нет "Arduino LLC" тогда делаем следующее:
a) Нажать "Установить с диска" "Have Disk" кнопку в том же окне.
b) Указать на папку с установленной средой ардуино (если она еще не установлена, значит нужно установить), в этой папке найти "drivers" подпапку, потом выбрать в ней файл с .inf расширением для нужного устройства (В данном случае Arduino UNO.inf).
6) Установить драйвер. Игнорировать предупреждение при установке.
7) Должен появится COM порт вместо unknown device. Ардуино IDE выбрать Tools > Serial Port и выбрать COM с нужным номером.
Скорее всего, так должно получиться. Если нет - надо смотреть в свойствах неизвестного устройства вкладку "Сведения", там выбрать в списке "Коды оборудования" им по этим кодам гуглить нужные драйверы, если в китайской ардуине стоит новый преобразователь USB 2 COM
Опечатка в посте или в программе?
includeВ - надо include, наверное буква B случайно нажалась на клавиатуре.
Поскольку библиотек к часам много,
- во-первых: они все рабочие,
- во-вторых: их много и они могут конфликтовать между собой,
я предложил бы два варианта:
Первый вариант: Указать "жесткие" пути к библиотекам часов в #include (вместо #include <DS1307RTC.h> написать #include "C:\Arduino\libraries\DS1307RTC/DS1307RTC.h"), поскольку
Форма в кавычках Препроцессор ищет включаемые файлы в следующем порядке:
1. В том же каталоге, где находится файл с оператором #include.
2. В каталогах открытых в данный момент включаемых файлов (в порядке, обратном тому, в котором они открывались). Поиск начинается в каталоге родительского включаемого файла, а затем выполняется в каталогах всех включаемых файлов-прародителей.
3. По путям, заданным всеми параметрами компилятора /I.
4. По путям, заданным в переменной среды INCLUDE.
Форма с угловыми скобками Препроцессор ищет включаемые файлы в следующем порядке:
1. По путям, заданным всеми параметрами компилятора /I.
2. Если компиляция выполняется из командной строки — по путям, которые заданы в переменной среды INCLUDE.
Ну в второй вариант, по принципу первого, переложить файлы h, cpp от библиотеки часов в каталог с ino, и изменить кавычки с угловых на двойные, вот так: #include "DS1307RTC.h". При открытии ino файла откроются в Arduino IDE дополнительные закладки с .h файлами, игнорим.
Третий вариант - хреновый, сделать поиск по компьютеру одноименных файлов библиотек часов, и ну и переименовывать лишние в DS1307RTC.h.old, например, оставив один какой-то DS1307RTC.h, предварительно проверив в нем наличие определений tmElements_t и пробовать.
Saddamko, продайте мелкий принтер )
Сожалею, но я его уже частично разобрал на доработку - во первых по одной оси проскальзывает иногда, и половина печатаемого может сдвинуться в сторону, и крепление экструдера отпечатал - чтобы пожестче конструкция была.
Плохая конструкция - все-таки в такой мелкоте чаще бывают проблемы, например - экструдер (та часть радиатора, где плавится) без вентилятора - поскольку вентилятор сильно утяжеляет конструкцию и шаговик еще чаще пропуски делает, так вот экструдер при длительной печати перегревается, пруток к нем расплывается, забивается, приходится все разбирать и выковыривать.
Так что и жалеть не надо.
Да и размеры - 38х38х38 мм. Я доработал это довольно известный принтер eWaste, так что он по вертикали 38 мм печатает, а в оригинале там шаговик от флопика - наверно мм 15 в высоту... Жабок только печатать:
http://www.instructables.com/id/eWaste-60-3DPrinter/
http://www.instructables.com/id/Curiosi … 3D-Printer
Непонял, что такое
TFunctionStatus flow_cmd_hello
А все остальное работает:
typedef int TE_TYPE_CONFIG_CMD ;
typedef struct {
char *CMD;
TE_TYPE_CONFIG_CMD COMMAND;
float TFunctionStatus;
// TFunctionStatus (*flow_)(unsigned long ID);
}TD_TEXT_CMD;
float flow_command_hello1,flow_command_hello2,flow_command_hello3,flow_command_hello4,flow_command_hello5,flow_command_hello6;
int COMMAND_HELLO1=1;
int COMMAND_HELLO2=2;
int COMMAND_HELLO3=3;
int COMMAND_HELLO4=4;
int COMMAND_HELLO5=5;
int COMMAND_HELLO6=6;
const TD_TEXT_CMD TEXT_CMD[] =
{
{"HELLO1" ,COMMAND_HELLO1, flow_command_hello1 },
{"HELLO2" ,COMMAND_HELLO2, flow_command_hello2 },
{"HELLO3" ,COMMAND_HELLO3, flow_command_hello3 },
{"HELLO4" ,COMMAND_HELLO4, flow_command_hello4 },
{"HELLO5" ,COMMAND_HELLO5, flow_command_hello5 },
{"HELLO6" ,COMMAND_HELLO6, flow_command_hello6 }
};
void setup() {
// put your setup code here, to run once:
int i;
Serial.begin(9600);
for (i=0; i<6; i++)
{
Serial.print(TEXT_CMD[i].CMD);Serial.print("=");Serial.println(TEXT_CMD[i].COMMAND);
}
}
void loop() {
// put your main code here, to run repeatedly:
}
Пишут, что в Aрдуино не реализован sprintf с %f, вроде по соображениям быстродействия - чтобы обойти эту проблему, предлагаю попробовать другой способ вывода float:
#include <stdio.h>
// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop()
{
char buffer[12];
float value = 12.987;
char str_temp[6];
/* 4 is mininum width, 2 is precision; float value is copied onto str_temp*/
dtostrf(value, 5, 3, str_temp);
sprintf(buffer,"%s F", str_temp);
Serial.println(buffer);
}
Собрал я его года три назад, исправно работает, иногда даже бывает полезен, когда нужно измерить размеры комнаты, проема двери или еще чего-нибудь.
Работает очень точно. Расстояние, которое можно измерить не очень большое - уверенно меряет до 4-х метров.
Использованный в устройстве датчик HC-SR04 содержит ультразвуковой излучатель и приемник, по времени отклика от предмета перед датчик определяется расстояние с достаточно высокой точностью.
Дальность измерения - примерно до 5 метров. Подключив к Arduino
данный датчик и, цифровой индикатор LCD 1602 (HD44780) по шине i2c, а самое главное, засунув все это в коробочку, а не оставив в виде макета, получил удобное и надежное устройство. Поскольку измерять приходится редко, чтобы уж не перевести устройство в разряд бесполезно валяющихся, добавил в него измеритель температуры на ds18B20.
После запуска поочередно выводит показания температуры и расстояния, что видно на двух картинках ниже:
Так устройство выглядит спереди - кнопка включения, приемная и передающая часть датчика, дырочка под лазерный диод и кнопка его включения, которые просто попутно поместились в коробочке. Прилепил я этот лазер, чтобы удобней было целиться в препятствие, к которому измеряем расстояние:
"Кишочки" - все обильно сдобрено пластиковым клеем из термопистолета. Видно, что LCD 1602 (HD44780) я использовал с припаяным к нему переходником, позволяющим управлять индикатором по i2c и уменьшить число проводов к индикатору.
Схема подключения индикатора к Ардуино по I2C:
Почитать подробней можно на https://lesson.iarduino.ru/page/urok-4- … k-arduino/
Желтый цилиндрик слева - это упомянутый лазерный диод, запитано все от батарейки "Крона" 9в, поскольку потребляемый ток устройством минимальный, штатных стабилизаторов питания на Ардуино вполне достаточно для понижения питания. Я вот смотрю на черную кляксу пластика в левом нижнем углу на снимке ниже, к которой идут провода, и кажется, я все-таки там поставил стабилизатор напряжения на 7805
Выглядит все ужасно, наверно самое полезное в описании - код, из которого можно какие-то кусочки использовать у себя в проектах. Мопед Код не мой, автор там указан, я немножко просто все собрал в кучу из разных источников.
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Ultrasonic.h>
/*
* HCSR04Ultrasonic/examples/UltrasonicDemo/UltrasonicDemo.pde
*
* SVN Keywords
* ----------------------------------
* $Author: cnobile $
* $Date: 2011-09-17 02:43:12 -0400 (Sat, 17 Sep 2011) $
* $Revision: 29 $
* ----------------------------------
*/
#define TRIGGER_PIN 10
#define ECHO_PIN 9
OneWire ow (2); // on pin 10
Ultrasonic ultrasonic(TRIGGER_PIN, ECHO_PIN);
// initialize the library with the numbers of the interface pins
LiquidCrystal_I2C lcd(0x27,16,2); /* Задаем размерность дисплея.
При использовании LCD I2C модуля с дисплеем 16х4 ничего в коде изменять не требуется, cледует только заменить цифру отвечающую за количество сторок */
int pos = 0; // variable to store the servo position
void setup()
{
Serial.begin(9600);
lcd.init(); // Инициализация lcd
lcd.backlight(); // Включаем подсветку
// Курсор находится в начале 1 строки
lcd.print("Temperature and"); // Выводим текст
lcd.setCursor(0, 1); // Устанавливаем курсор в начало 2 строки
lcd.print("Ultrasonic mtr. "); // Выводим текст
delay (1000);
lookUpSensors();
delay (1000);
}
void loop()
{
int led = 13;
float cmMsec, inMsec;
long microsec = ultrasonic.timing();
cmMsec = ultrasonic.convert(microsec, Ultrasonic::CM);
inMsec = ultrasonic.convert(microsec, Ultrasonic::IN);
//inMsec= int(inMsec);
myLCDclear();
lcd.setCursor(0, 0);
lcd.print("Ultrasonic ");
lcd.setCursor(0, 1);
lcd.print("dist.(cm:)");
lcd.print (cmMsec);
delay (2000);
Temp ();
delay (2000);
}
void Temp ()
{
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;
if (! ow.search (addr)) {
ow.reset_search ();
delay (250);
return;
}
ow.reset ();
ow.select (addr);
ow.write (0x44,1); // start conversion, with parasite power on at the end
delay (1000); // maybe 750ms is enough, maybe not
// we might do a ow.depower () here, but the reset will take care of it.
present = ow.reset ();
ow.select (addr);
ow.write (0xBE); // Read Scratchpad
for (i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ow.read ();
}
// convert the data to actual temperature
unsigned int raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// count remain gives full 12 bit resolution
// raw = (raw & 0xFFF0) + 12 — data[6];
}
} else {
byte cfg = (data[4] & 0x60);
if (cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;
myLCDclear();
lcd.setCursor(0, 0);
lcd.print ("Temperature =");
lcd.setCursor(0, 1);
lcd.print (celsius);
lcd.print (" C, ");
lcd.print (fahrenheit);
lcd.println (" F ");
}
void lookUpSensors(){
byte address[8];
int i=0;
byte ok = 0, tmp = 0;
//start the search
lcd.setCursor(0, 0);
while (ow.search(address)){
tmp = 0;
//0x10 = DS18S20
if (address[0] == 0x10){
lcd.print("This is a DS18S20: ");
tmp = 1;
} else {
//0x28 = DS18B20
if (address[0] == 0x28){
lcd.print("This is a DS18B20: ");
tmp = 1;
}
}
lcd.setCursor(0, 1);
//display the address, if tmp is ok
if (tmp == 1){
if (OneWire::crc8(address, 7) != address[7]){
lcd.println("but it doesn't have a valid CRC!");
} else {
//all is ok, display it
for (i=0;i<8;i++){
if (address[i] < 9){
lcd.print("0");
}
lcd.print(address[i],HEX);
if (i<7){
lcd.print("");
}
}
lcd.println("");
ok = 1;
}
}//end if tmp
}//end while
if (ok == 0){
lcd.println("No devices were found");
}
}
void myLCDclear()
{
lcd.setCursor(0, 0);
lcd.print (" ");
lcd.setCursor(0, 1);
lcd.print (" ");
}
Похоже, это все-таки проблема. Если говорить о шифровании, как о кодировке передаваемых данных - так действительно, сниффером неважно какие данные снимать - снял поток, и повторно отправил. А если по аналогии с SSL шифрованием - то просто нет ресурсов в ардуине реализовать даже упрошенный вариант. Обмен сертификатами, с проверкой достоверности, как минимум, серверного, обмен доступными протоколами шифрования - это и не нужно. И после удачных этих этапов идет шифрованный поток на рандомном ключе, которым обмениваются точки в момент "снюхивания". Ну сертификат, допустим, можно отбросить, метод шифрования, понятно один выбрать. Тогда реализация шифрования может быть такая - в момент установления каждой сессии между двумя Ардуинами генерировать рандом, обмениваться им, и затем гнать трафик шифрованый этим рандомом. Если сниффер повторно пошлет поток, но на приемной стороне уже другой рандомный ключ, и взлома не будет.
Ну это теоретически, как это увяжется в код я не знаю, я стратег
Захотелось сделать устройство записи треков GPS по причине того, что использовать телефон для таких целей не очень удобно, поскольку Android телефон и так не очень хорошо держит зарядку. Пользоваться на нем навигатором иногда очень удобно, но на длительное время его включать - значит рисковать остаться без связи в нужный момент. Альтернативой у меня есть внешний Bluetooth GPS приемник, который можно использовать вместе с ноутбуком, но по аналогичным проблемам с электропитанием, его использование тоже не устраивает. Хотелось иметь небольшое устройство, которое можно включить, и забыть про него. Не контролировать заряд аккумулятора. Чтобы оно записывало информацию, и не теряло.
Поэтому был куплен модуль GPS приемника, с выходами уровня TTL (Rx, Tx), Ардуино и модуль EEPROM памяти на чипе AT24C256. Также понадобился контроллер заряда аккумулятора, сам аккумулятор, корпус и миниатюрный включатель питания.
Все это было собрано в кучку, соединено проводами и уже работает.
Что умеет:
1. Записывать GPS трек в течение нескольких часов, больше 6 часов точно, еще не замерял максимальное время работы.
2. Выгружать записанные треки по последовательному интерфейсу в форматах GPX и KML.
3. Сохраняет трек в энергонезависимой памяти, поэтому даже резкое отключение питание или разрядка аккумулятора, не разрушит записанную информацию, которую можно выгрузить после включения устройства в любое время.
Как им пользоваться:
После включения устройство ожидает команды по последовательному интерфейсу, если нет подключения к компьютеру и нет команд, через 3 минуты автоматически переходит в режим записи. После получения уверенного сигнала со спутников начинается запись в первую из 2048 записей трека. Каждую минуту добавляется новая запись.
При подключении к компьютеру устройство переходит в режим приема команд.
Обмен происходит через последовательный интерфейс, как при обычном подключении Ардуино к компьютеру. Можно для обмена информацией использовать любую другую терминальную программу, работающую с COM портами, например Putty.
Команды следующие:
K - Отправить на компьютер текст в формате KML файла (Send to PC in KML format)
D - Вывести шестнадцатеричный дамп EEPROM памяти для контроля заполнения (HEX dump of EEPROM memory)
E - Заполнить содержимое EEPROM памяти нулями (стереть)(Erase EEPROM data)
R - Запустить процесс сохранения в памяти координат (запись трека) (Start recording of GPS data)
G - Отправить на компьютер текст в формате GPX файла (Send to PC in GPX format)
Результаты вывода в консоль руками копируем и сохраняет в текстовые файлы, которые потом можно загрузить в Google Maps, например.
Вот пример загруженного на Google Maps GPX файла из устройства:
Выглядит устройство внутри так:
В правой части корпуса - аккумулятор LiIon, контроллер его заряда и включатель питания:
В левой части корпуса - GPS приемник, и под ним, под пластмассовой перегородкой из синей пластмассы - Arduino Nano. НА Ардуино имеется преобразователь USB2COM, поэтому для подключения к компьютеру достаточно обычного MiniUSB кабеля. Разъем Ардуино MiniUSB доступен снаружи через отверстие в корпусе и может использоваться для программирования, а также для получения данных в компьютер.
Для подключения к Ардуино GPS приемника используются контакт Ардуино D2 (software serial), точнее, выход Tx GPS приемника подключен к D2 Ардуино.
Для EEPROM памяти используются контакты A4 A5 Ардуино (стандартное подключение по I2C протоколу).
Модуль памяти EEPROM размером 32 килобайта (256 Килобит) позволяет записать 2048 точек в треке, поскольку под одну точку в треке используется 16 байт (помимо координат, записывается дата и время замера, скорость, высота и др. информация из GPS NMEA потока - подробности в программе можно увидеть).
Код для проекта собрал из нескольких источников, код очень сырой, будет допиливаться, но в данный момент все достаточно удобно для меня работает, и можно уже опубликовать:
#include <SoftwareSerial.h>
#include <Wire.h> //I2C library
#include <TinyGPS++.h>
/*
The TinyGPS++ Object Model
The main TinyGPS++ object contains several core sub-objects:
location – the latest position fix
date – the latest date fix (UT)
time – the latest time fix (UT)
speed – current ground speed
course – current ground course
altitude – latest altitude fix
satellites – the number of visible, participating satellites
hdop – horizontal diminution of precision
*/
/*
charsProcessed() – the total number of characters received by the object
sentencesWithFix() – the number of $GPRMC or $GPGGA sentences that had a fix
failedChecksum() – the number of sentences of all types that failed the checksum test
passedChecksum() – the number of sentences of all types that passed the checksum test
*/
/* This sample code demonstrates the normal use of a TinyGPSPlus object.
It requires the use of SoftwareSerial, and assumes that you have a
9600-baud serial GPS device hooked up on pins 2(rx) and 3(tx).
Summary:
This software displays information from an EM 406A GPS sensor on Phi-1 shield's LCD screen. It also logs the GPS information to the onboard EEPROM of the Phi-1 shield.
Sample GPS data:
Lat/Long(10^-5 deg): 45xxxxx, -94xxxxx
Date(ddmmyy): 281210 Time(hhmmsscc): 134000
Alt(cm): 31750 Speed(mph): 1.81
List of functions:
* Menu gives you several choices:
* Send to PC: sends recorded GPS information to PC via the USB connection.
Two modes are available:
Verbose mode generates information as shown above.
Non-verbose mode sends only the column labels followed by tab-separated data, ideal for spreasheet programs to import. You may copy and paste.
* Erase EEPROM: erases the EEPROM
* Record: records GPS information, lattitude, longitude, altitude, date, time, speed to EEPROM
* Display: displays the GPS coordinates without recording
* Parameters: allows the user to adjust parameters such as period between two consecutive recordings,, PC data format, to start recording at which data entry and end at which entry.
* Up and down cycle through the menu options.
* Left, right, B act as confirm or enter.
* A escapes and only will preserve the latest value.
*/
#define EEPROM_size 32768UL // This is the maximal bytes on your eeprom, depending on the chip you use. I'm using 24LC256, with 256KiloBits so 32KiloBytes=32768 bytes.
#define n_menu_items 5
#define menu_PC 0 //'Pp'
#define menu_erase 1 //'Ee'
#define menu_record 2 //'Rr'
#define menu_dump 3 //'Dd'
#define menu_para 4
#define menu_KML 5 //'Kk'
#define menu_GPX 6 //'Gg'
#define menu_none 7
#define GPS_Tx 3
#define GPS_Rx 2
// Global Variables
int command = menu_none; // This is the command char, in ascii form, sent from the serial port
boolean GotCommand=false;
boolean recording=false; // This indicates whether the program is recording the GPS info. If it is recording, a symbol "a chip" appears on the bottom right corner of the LCD.
boolean verbose=false; // This indicates the output to PC format. Verbose is for a human to read with "Lat/long:" and such. While not in verbose mode, it transfers faster and is more compatible with a spreadsheet program.
unsigned long period=5; // This is the period in seconds between two consecutive GPS recordings.
unsigned long pointer=0; // This pointer points to the next empty EEPROM byte for storing or next unread EEPROM byte for reading.
unsigned long lower_limit=0; // This is the lower limit to the pointer value. Save mode startssaving from this EEPROM address. If you use less than 4MBit EEPROM, there is no problem. If not, the limits can go beyond the limit of the signed integer taken by the input function.
unsigned long upper_limit=EEPROM_size; // This is the upper limit to the pointer value. Once the pointer is equal to this value, save mode will stop saving and quits to menu.
unsigned long start;
TinyGPSPlus gps;
SoftwareSerial ss(GPS_Rx, GPS_Tx);
void setup()
{
Wire.begin(); // initialize wire
Serial.begin(9600);
ss.begin(9600);
Serial.println("");
Serial.print("Library version: ");
Serial.println(TinyGPSPlus::libraryVersion());
// Serial.println("K - Send to PC in KML format");
// Serial.println("D - HEX dump of EEPROM memory");
// Serial.println("E - Erase EEPROM data");
// Serial.println("R - Start recording of GPS data");
// Serial.println("G - Send to PC in GPX format");
}
void loop()
{
do_menu();
if ((millis()> 180000)and (GotCommand==false))
{
// Serial.println ("No commands is received, start recording!");
_record();
};
}
void GPS_to_EEPROM(unsigned long *pointer)
/*
The function assumes that the TinyGPSPlus object gps is already initialized and ready to send data.
It also assumes that the caller feeds the GPS and checks the pointer so the pointed address will not exceed the address space of the EEPROM, or cross page boundaries while writing.
*/
{
double spdf;
unsigned long spd;
float lat, lon;
long alt;
unsigned long age, dat, tim;
float buf[4];
lat=gps.location.lat();
lon=gps.location.lng();
age=gps.location.age();
alt=gps.altitude.meters();
spdf=gps.speed.kmph();
dat=gps.date.value();
tim=gps.time.value();
spd=spdf*100;
buf[0]=lat;
buf[1]=lon;
buf[2]=((alt/10)<<16)|((dat/10000)<<11)|(((dat%10000)/100)<<7)|(dat%100); // Altitude only takes 16 bit. It is in the unit of 0.1m instead of 1cm, which is not necessary in accuracy. date(when expressed in binary 5bit date-4bit month-7bit year, takes no more than 16 bit. Combine them together.
buf[3]=(spd<<17)|((tim/1000000)*3600+((tim%1000000)/10000)*60+(tim%10000)/100); // Speed, expressed in 1/100 mph, takes less than 15 bits. Compact hhmmsscc into seconds since 00:00 and lose the 1/100 seconds. This is 17 bit long.
i2c_eeprom_write_page(0x50, (unsigned int) (*pointer), (byte*) buf, 16); // Store 16 bytes of data at location of the pointer.
(*pointer)=(*pointer)+16; // Increment pointer.
delay(5); // Make sure the data is written to the EEPROM.
}
boolean EEPROM_to_GPS(float *lat, float *lon, long *alt, unsigned long *tim, unsigned long *dat, double *spdf, unsigned long *pointer)
/*
This function reads one EEPROM entry, if it's non zero, parse it into long integer forms (double precision for speed), and returns true.
If the EEPROM entry is empty, return false.
To stay isolated from the main program, this function doesn't check if the pointer will be beyond the EEPROM size, which is left to the caller to do.
*/
{
float buf[4];
i2c_eeprom_read_buffer (0x50, (unsigned int) (*pointer), (byte*) buf, 16);
if ((buf[0]==0)&&(buf[1]==0)&&(buf[2]==0)&&(buf[3]==0)) return false;
*lat=(float)buf[0];
*lon=(float)buf[1];
*dat=(long)buf[2]&0xFFFF;
*dat=(*dat>>11)*10000+((*dat>>7)&15)*100+(*dat&127); //Process data to turn into 12/27/10 form
*alt=10*((long)buf[2]>>16);
*tim=((long)buf[3]&0x1FFFF);
*tim=(*tim/3600)*1000000+((*tim%3600)/60)*10000+(*tim%60)*100; //Process time to turn into 12:59:0000 form
*spdf=((double)(((long)buf[3])>>17))/100.0;
(*pointer)=(*pointer)+16; // Increment pointer by 16 bytes.
return true;
}
void do_menu()
{
int temp1=AskMode ();
switch (temp1)
{
case menu_dump:
_print_EEPROM_dump();
break;
case menu_erase:
_erase();
break;
case menu_record:
_record();
break;
case menu_para:
_parameters();
break;
case menu_PC:
_send_to_PC();
break;
case menu_KML:
_send_to_PC_KML();
break;
case menu_GPX:
_send_to_PC_GPX();
break;
}
if (temp1 != menu_none) {
Serial.print("Command is completed");
command = menu_none;
}
}
int AskMode ()
{
if (Serial.available()) { // Look for char in serial que and process if found
command = Serial.read();
if (command == (byte)'P' || command == (byte)'p') { //If command = "Pp" Send GPS to PC
command = menu_PC;
GotCommand=true;
}
else if (command == (byte)'E' || command == (byte)'e') { //If command = "Ee" Erase EEPROM
command = menu_erase;
GotCommand=true;
}
else if (command == (byte)'D' || command == (byte)'d') { //If command = "Dd" Dump EEPROM
command = menu_dump;
GotCommand=true;
}
else if (command == (byte)'R' || command == (byte)'r') { //If command = "Rr" Record GPS
command = menu_record;
GotCommand=true;
}
else if (command == (byte)'G' || command == (byte)'g') { //If command = "Gg" send GPX
command = menu_GPX;
GotCommand=true;
}
else if (command == (byte)'K' || command == (byte)'k') { //If command = "Kk" send KML
command = menu_KML;
GotCommand=true;
}
else {
command = menu_none; // none command
};
if (command != menu_none){
Serial.print("Command: "); Serial.println(command); // Echo command CHAR in ascii that was sent
}
}
delay(100);
return command;
}
void _send_to_PC()
{
double spdf;
unsigned long spd;
float lat, lon;
long alt;
unsigned long age, dat, tim;
unsigned long buf[4];
pointer=0;
while (EEPROM_to_GPS(&lat, &lon, &alt, &tim, &dat, &spdf, &pointer)&&(pointer<=EEPROM_size-16))
{
Serial.print("Lat/Long(10^-5 deg): "); Serial.print(lat,6); Serial.print(", "); Serial.print(lon,6); Serial.println("");
Serial.print("Date(ddmmyy): "); Serial.print(dat); Serial.print(" Time(hhmmsscc): "); Serial.print(tim); Serial.println("");
Serial.print("Alt(cm): "); Serial.print(alt); Serial.print(" Speed(mph): "); Serial.print(spdf,2); Serial.println(""); Serial.println("");
}
pointer=0;
}
void _send_to_PC_GPX()
{
double spdf;
unsigned long spd;
float lat, lon;
long alt;
unsigned long age, dat, tim;
unsigned long buf[4];
pointer=0;
Serial.println ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
Serial.println ("<gpx xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"1.0\"");
Serial.println ("xmlns=\"http://www.topografix.com/GPX/1/0\" creator=\"Polar WebSync 2.3 - www.polar.fi\"");
Serial.println ("xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">");
Serial.println ("<time>2011-09-22T18:56:51Z</time>");
Serial.println ("<trk>");
Serial.println ("<name>exercise</name>");
Serial.println ("<trkseg>");
while (EEPROM_to_GPS(&lat, &lon, &alt, &tim, &dat, &spdf, &pointer)&&(pointer<=EEPROM_size-16))
{
Serial.print ("<trkpt lat=\""); Serial.print(lat, 6); Serial.print("\" lon=\""); Serial.print(lon,6); Serial.print ("\">");
Serial.print ("<time>"); Serial.print(gps.date.year()); Serial.print ("-"); Serial.print(gps.date.month()); Serial.print ("-"); Serial.print(gps.date.day()); Serial.print ("T"); Serial.print(gps.time.hour()); Serial.print (":"); Serial.print(gps.time.minute()); Serial.print (":"); Serial.print(gps.time.second()); Serial.print ("Z</time>");
Serial.println ("</trkpt>");
}
Serial.println ("</trkseg>");
Serial.println ("</trk>");
Serial.println ("</gpx>");
pointer=0;
}
void _send_to_PC_KML()
{
double spdf;
unsigned long spd;
float lat, lon;
long alt;
unsigned long age, dat, tim;
unsigned long buf[4];
pointer=0;
Serial.println ("<?xml version=\"1.0\" standalone=\"yes\"?>");
Serial.println ("<kml xmlns=\"http://earth.google.com/kml/2.1\">");
Serial.println ("<Placemark>");
Serial.println ("<name>Kiev</name>");
Serial.println ("<description>Data from Arduino GPS DIY Logger</description>");
while (EEPROM_to_GPS(&lat, &lon, &alt, &tim, &dat, &spdf, &pointer)&&(pointer<=EEPROM_size-16))
{
Serial.println ("<Point>");
Serial.print ("<coordinates>"); Serial.print(lon, 6); Serial.print(","); Serial.print(lat,6); Serial.print ("</coordinates>");
Serial.println ("</Point>");
}
Serial.println ("</Placemark>");
Serial.println ("</kml>");
pointer=0;
}
void _erase()
{
int temp1, temp2;
unsigned long buf[4]={0,0,0,0};
temp1=1;
Serial.println ("EEPROM Erasing...");
if (temp1)
{
for (unsigned long addr=0;addr<EEPROM_size;addr+=16)
{
i2c_eeprom_write_page( 0x50, addr, (byte*) buf, 16);
delay(5);
}
}
Serial.println ("Erased!");
}
void _print_EEPROM_dump ()
{
int addr, i, j=0;
byte b = i2c_eeprom_read_byte(0x50, addr);
// Serial.println("Start dump:");
for (i=0;i<10; i++)
{
for (j=0;j<16; j++)
{
Serial.print(b, HEX); Serial.print(" ");
addr++;
b = i2c_eeprom_read_byte(0x50, addr);
}
Serial.println("#");
}
}
void _record()
{
double spdf;
unsigned long spd;
float lat, lon, alt;
unsigned long age, dat, tim;
unsigned long buf[4];
char msg[17];
bool newdata = false;
unsigned long start = millis();
Serial.println ("Record GPS data is started now!");
// Every few seconds we print an update
pointer=lower_limit; // Load the lower limit.
recording = true;
while(pointer <upper_limit)
{
while (ss.available() > 0)
gps.encode(ss.read());
start=millis();
if (gps.location.isUpdated() || gps.altitude.isUpdated())
{
GPS_Test ();
if (recording)
{
if (pointer<upper_limit)
{
GPS_to_EEPROM(&pointer);
delay (60000);
}
else
{
Serial.print("Limit reached");
return;
}
}
}
}
}
void _parameters()
{
}
void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data )
{
int rdata = data;
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddress >> 8)); // MSB
Wire.write((int)(eeaddress & 0xFF)); // LSB
Wire.write(rdata);
Wire.endTransmission();
}
// WARNING: address is a page address, 6-bit end will wrap around
// also, data can be maximum of about 30 bytes, because the Wire library has a buffer of 32 bytes
void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length )
{
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddresspage >> 8)); // MSB
Wire.write((int)(eeaddresspage & 0xFF)); // LSB
byte c;
for ( c = 0; c < length; c++)
Wire.write(data[c]);
Wire.endTransmission();
}
byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress )
{
byte rdata = 0xFF;
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddress >> 8)); // MSB
Wire.write((int)(eeaddress & 0xFF)); // LSB
Wire.endTransmission();
Wire.requestFrom(deviceaddress,1);
if (Wire.available()) rdata = Wire.read();
return rdata;
}
// maybe let's not read more than 30 or 32 bytes at a time!
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length )
{
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddress >> 8)); // MSB
Wire.write((int)(eeaddress & 0xFF)); // LSB
Wire.endTransmission();
Wire.requestFrom(deviceaddress,length);
int c = 0;
for ( c = 0; c < length; c++ )
if (Wire.available()) buffer[c] = Wire.read();
}
void GPS_Test ()
{
Serial.println(gps.location.lat(), 6); // Latitude in degrees (double)
Serial.println(gps.location.lng(), 6); // Longitude in degrees (double)
Serial.print(gps.location.rawLat().negative ? "-" : "+");
Serial.println(gps.location.rawLat().deg); // Raw latitude in whole degrees
Serial.println(gps.location.rawLat().billionths);// ... and billionths (u16/u32)
Serial.print(gps.location.rawLng().negative ? "-" : "+");
Serial.println(gps.location.rawLng().deg); // Raw longitude in whole degrees
Serial.println(gps.location.rawLng().billionths);// ... and billionths (u16/u32)
Serial.println(gps.date.value()); // Raw date in DDMMYY format (u32)
Serial.println(gps.date.year()); // Year (2000+) (u16)
Serial.println(gps.date.month()); // Month (1-12) (u8)
Serial.println(gps.date.day()); // Day (1-31) (u8)
Serial.println(gps.time.value()); // Raw time in HHMMSSCC format (u32)
Serial.println(gps.time.hour()); // Hour (0-23) (u8)
Serial.println(gps.time.minute()); // Minute (0-59) (u8)
Serial.println(gps.time.second()); // Second (0-59) (u8)
Serial.println(gps.time.centisecond()); // 100ths of a second (0-99) (u8)
Serial.println(gps.speed.value()); // Raw speed in 100ths of a knot (i32)
Serial.println(gps.speed.knots()); // Speed in knots (double)
Serial.println(gps.speed.mph()); // Speed in miles per hour (double)
Serial.println(gps.speed.mps()); // Speed in meters per second (double)
Serial.println(gps.speed.kmph()); // Speed in kilometers per hour (double)
Serial.println(gps.course.value()); // Raw course in 100ths of a degree (i32)
Serial.println(gps.course.deg()); // Course in degrees (double)
Serial.println(gps.altitude.value()); // Raw altitude in centimeters (i32)
Serial.println(gps.altitude.meters()); // Altitude in meters (double)
Serial.println(gps.altitude.miles()); // Altitude in miles (double)
Serial.println(gps.altitude.kilometers()); // Altitude in kilometers (double)
Serial.println(gps.altitude.feet()); // Altitude in feet (double)
Serial.println(gps.satellites.value()); // Number of satellites in use (u32)
Serial.println(gps.hdop.value()); // Horizontal Dim. of Precision (100ths-i32)
}
Сеанс работы с модулем выглядит так:
Library version: 0.92
Command: 3
8F C3 49 42 7E 0 F5 41 0 51 4F 49 0 7B 3F 47 #
35 C3 49 42 C5 FF F4 41 0 51 4F 49 B8 FD C5 49 #
41 C3 49 42 F8 FF F4 41 0 51 5F 49 A0 FF C5 49 #
3F C3 49 42 C1 FF F4 41 0 51 6F 49 88 1 C6 49 #
15 C3 49 42 B3 FF F4 41 0 51 6F 49 1B B0 41 4C #
3E C3 49 42 B4 FF F4 41 0 51 7F 49 2A B0 41 4C #
E9 C2 49 42 68 FF F4 41 0 51 7F 49 3A 30 14 4C #
CD C2 49 42 2A FF F4 41 80 A8 8F 49 49 30 14 4C #
AF C2 49 42 F FF F4 41 80 A8 97 49 58 30 14 4C #
8F C2 49 42 BC FE F4 41 80 A8 97 49 67 30 2E 4C #
Command is completed
Command: 6
<?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"
xmlns="http://www.topografix.com/GPX/1/0" creator="Polar WebSync 2.3 - www.polar.fi"
xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
<time>2016-10-31T12:00:00Z</time>
<trk>
<name>exercise</name>
<trkseg>
<trkpt lat="50.440994" lon="30.628486"><time>2016-11-1T6:40:0Z</time></trkpt>
<trkpt lat="50.438034" lon="30.629999"><time>2016-11-1T6:41:0Z</time></trkpt>
<trkpt lat="50.436225" lon="30.631147"><time>2016-11-1T6:32:0Z</time></trkpt>
<trkpt lat="50.433849" lon="30.632692"><time>2016-11-1T6:36:0Z</time></trkpt>
<trkpt lat="50.431716" lon="30.633689"><time>2016-11-1T6:40:0Z</time></trkpt>
<trkpt lat="50.429172" lon="30.635606"><time>2016-11-1T6:44:0Z</time></trkpt>
<trkpt lat="50.427814" lon="30.636674"><time>2016-11-1T7:48:0Z</time></trkpt>
<trkpt lat="50.427806" lon="30.637451"><time>2016-11-1T7:52:0Z</time></trkpt>
<trkpt lat="50.428657" lon="30.640392"><time>2016-11-1T7:56:0Z</time></trkpt>
<trkpt lat="50.429931" lon="30.644645"><time>2016-11-1T7:0:0Z</time></trkpt>
<trkpt lat="50.430488" lon="30.644224"><time>2016-11-1T7:4:0Z</time></trkpt>
<trkpt lat="50.430534" lon="30.643608"><time>2016-11-1T7:36:0Z</time></trkpt>
<trkpt lat="50.430465" lon="30.643112"><time>2016-11-1T7:40:0Z</time></trkpt>
<trkpt lat="50.430507" lon="30.643178"><time>2016-11-1T7:44:0Z</time></trkpt>
<trkpt lat="50.430389" lon="30.643089"><time>2016-11-1T7:48:0Z</time></trkpt>
<trkpt lat="50.430519" lon="30.643329"><time>2016-11-1T7:52:0Z</time></trkpt>
<trkpt lat="50.430461" lon="30.643135"><time>2016-11-1T7:56:0Z</time></trkpt>
<trkpt lat="50.430538" lon="30.643316"><time>2016-11-1T7:0:0Z</time></trkpt>
<trkpt lat="50.430427" lon="30.642770"><time>2016-11-1T7:4:0Z</time></trkpt>
<trkpt lat="50.430683" lon="30.643207"><time>2016-11-1T7:8:0Z</time></trkpt>
<trkpt lat="50.430622" lon="30.643318"><time>2016-11-1T7:12:0Z</time></trkpt>
<trkpt lat="50.430511" lon="30.643299"><time>2016-11-1T7:16:0Z</time></trkpt>
<trkpt lat="50.430458" lon="30.643127"><time>2016-11-1T7:48:0Z</time></trkpt>
<trkpt lat="50.430419" lon="30.643144"><time>2016-11-1T7:52:0Z</time></trkpt>
<trkpt lat="50.430500" lon="30.643247"><time>2016-11-1T7:56:0Z</time></trkpt>
<trkpt lat="50.430492" lon="30.643100"><time>2016-11-1T7:0:0Z</time></trkpt>
<trkpt lat="50.430541" lon="30.643268"><time>2016-11-1T7:4:0Z</time></trkpt>
<trkpt lat="50.430492" lon="30.643062"><time>2016-11-1T7:8:0Z</time></trkpt>
<trkpt lat="50.430683" lon="30.643390"><time>2016-11-1T7:12:0Z</time></trkpt>
<trkpt lat="50.430511" lon="30.643236"><time>2016-11-1T7:16:0Z</time></trkpt>
<trkpt lat="50.430553" lon="30.643251"><time>2016-11-1T7:20:0Z</time></trkpt>
<trkpt lat="50.430622" lon="30.643255"><time>2016-11-1T7:24:0Z</time></trkpt>
<trkpt lat="50.430755" lon="30.643877"><time>2016-11-1T7:28:0Z</time></trkpt>
<trkpt lat="50.430438" lon="30.643171"><time>2016-11-1T7:32:0Z</time></trkpt>
<trkpt lat="50.430538" lon="30.643449"><time>2016-11-1T7:36:0Z</time></trkpt>
<trkpt lat="50.430694" lon="30.643373"><time>2016-11-1T7:8:0Z</time></trkpt>
<trkpt lat="50.430473" lon="30.643560"><time>2016-11-1T7:12:0Z</time></trkpt>
<trkpt lat="50.430500" lon="30.643421"><time>2016-11-1T7:16:0Z</time></trkpt>
<trkpt lat="50.430461" lon="30.643058"><time>2016-11-1T7:20:0Z</time></trkpt>
<trkpt lat="50.429500" lon="30.638359"><time>2016-11-1T7:24:0Z</time></trkpt>
<trkpt lat="50.427513" lon="30.630750"><time>2016-11-1T7:28:0Z</time></trkpt>
<trkpt lat="50.425941" lon="30.623737"><time>2016-11-1T7:32:0Z</time></trkpt>
<trkpt lat="50.431198" lon="30.616735"><time>2016-11-1T7:36:0Z</time></trkpt>
<trkpt lat="50.436553" lon="30.613574"><time>2016-11-1T7:40:0Z</time></trkpt>
<trkpt lat="50.444984" lon="30.608430"><time>2016-11-1T7:44:0Z</time></trkpt>
<trkpt lat="50.451854" lon="30.604282"><time>2016-11-1T7:48:0Z</time></trkpt>
<trkpt lat="50.452846" lon="30.603673"><time>2016-11-1T7:20:0Z</time></trkpt>
<trkpt lat="50.459339" lon="30.598125"><time>2016-11-1T7:24:0Z</time></trkpt>
<trkpt lat="50.466320" lon="30.592060"><time>2016-11-1T7:28:0Z</time></trkpt>
<trkpt lat="50.472824" lon="30.586578"><time>2016-11-1T7:32:0Z</time></trkpt>
<trkpt lat="50.478488" lon="30.581762"><time>2016-11-1T7:36:0Z</time></trkpt>
<trkpt lat="50.479003" lon="30.581178"><time>2016-11-1T7:40:0Z</time></trkpt>
<trkpt lat="50.482902" lon="30.574560"><time>2016-11-1T7:44:0Z</time></trkpt>
<trkpt lat="50.483150" lon="30.573579"><time>2016-11-1T7:48:0Z</time></trkpt>
<trkpt lat="50.483917" lon="30.570413"><time>2016-11-1T7:52:0Z</time></trkpt>
<trkpt lat="50.484176" lon="30.557836"><time>2016-11-1T7:56:0Z</time></trkpt>
<trkpt lat="50.484161" lon="30.547096"><time>2016-11-1T7:28:0Z</time></trkpt>
<trkpt lat="50.484249" lon="30.538497"><time>2016-11-1T7:32:0Z</time></trkpt>
<trkpt lat="50.484031" lon="30.532958"><time>2016-11-1T7:36:0Z</time></trkpt>
<trkpt lat="50.484157" lon="30.524370"><time>2016-11-1T7:40:0Z</time></trkpt>
<trkpt lat="50.484184" lon="30.515460"><time>2016-11-1T7:44:0Z</time></trkpt>
<trkpt lat="50.484466" lon="30.506853"><time>2016-11-1T7:48:0Z</time></trkpt>
<trkpt lat="50.485046" lon="30.498723"><time>2016-11-1T7:52:0Z</time></trkpt>
<trkpt lat="50.485145" lon="30.497272"><time>2016-11-1T7:56:0Z</time></trkpt>
<trkpt lat="50.485839" lon="30.492294"><time>2016-11-1T8:0:0Z</time></trkpt>
<trkpt lat="50.489120" lon="30.483161"><time>2016-11-1T8:4:0Z</time></trkpt>
<trkpt lat="50.489238" lon="30.483140"><time>2016-11-1T8:52:0Z</time></trkpt>
<trkpt lat="50.488643" lon="30.484096"><time>2016-11-1T8:56:0Z</time></trkpt>
<trkpt lat="50.488353" lon="30.483186"><time>2016-11-1T8:0:0Z</time></trkpt>
<trkpt lat="50.488304" lon="30.481788"><time>2016-11-1T8:56:0Z</time></trkpt>
<trkpt lat="50.488121" lon="30.480539"><time>2016-11-1T8:0:0Z</time></trkpt>
<trkpt lat="50.488391" lon="30.479782"><time>2016-11-1T8:56:0Z</time></trkpt>
<trkpt lat="50.488334" lon="30.478380"><time>2016-11-1T8:0:0Z</time></trkpt>
<trkpt lat="50.488246" lon="30.477094"><time>2016-11-1T8:0:0Z</time></trkpt>
<trkpt lat="50.488967" lon="30.476121"><time>2016-11-1T8:0:0Z</time></trkpt>
<trkpt lat="50.489303" lon="30.475259"><time>2016-11-1T8:4:0Z</time></trkpt>
<trkpt lat="50.491306" lon="30.475305"><time>2016-11-1T8:4:0Z</time></trkpt>
</trkseg>
</trk>
</gpx>
Command is completed
Command: 5
<?xml version="1.0" standalone="yes"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<Placemark>
<name>Kiev</name>
<description>Data from Arduino GPS DIY Logger</description>
<Point>
<coordinates>30.625240,50.440975</coordinates></Point>
<Point>
<coordinates>30.624887,50.440631</coordinates></Point>
<Point>
<coordinates>30.624984,50.440677</coordinates></Point>
<Point>
<coordinates>30.624879,50.440670</coordinates></Point>
<Point>
<coordinates>30.624853,50.440509</coordinates></Point>
<Point>
<coordinates>30.624855,50.440666</coordinates></Point>
<Point>
<coordinates>30.624710,50.440341</coordinates></Point>
<Point>
<coordinates>30.624591,50.440235</coordinates></Point>
<Point>
<coordinates>30.624540,50.440120</coordinates></Point>
<Point>
<coordinates>30.624382,50.439998</coordinates></Point>
<Point>
<coordinates>30.624336,50.439952</coordinates></Point>
<Point>
<coordinates>30.624345,50.440029</coordinates></Point>
<Point>
<coordinates>30.624279,50.439929</coordinates></Point>
<Point>
<coordinates>30.624334,50.440013</coordinates></Point>
<Point>
<coordinates>30.624294,50.440078</coordinates></Point>
<Point>
<coordinates>30.624567,50.440319</coordinates></Point>
<Point>
<coordinates>30.624744,50.440414</coordinates></Point>
<Point>
<coordinates>30.625295,50.441028</coordinates></Point>
<Point>
<coordinates>30.625415,50.441131</coordinates></Point>
<Point>
<coordinates>30.625429,50.441154</coordinates></Point>
<Point>
<coordinates>30.625413,50.441139</coordinates></Point>
<Point>
<coordinates>30.625398,50.441131</coordinates></Point>
<Point>
<coordinates>30.625398,50.441131</coordinates></Point>
<Point>
<coordinates>30.625381,50.441116</coordinates></Point>
<Point>
<coordinates>30.625383,50.441116</coordinates></Point>
<Point>
<coordinates>30.625322,50.441089</coordinates></Point>
<Point>
<coordinates>30.625339,50.441085</coordinates></Point>
<Point>
<coordinates>30.625350,50.441085</coordinates></Point>
<Point>
<coordinates>30.625417,50.441101</coordinates></Point>
<Point>
<coordinates>30.625402,50.441089</coordinates></Point>
<Point>
<coordinates>30.625429,50.441104</coordinates></Point>
<Point>
<coordinates>30.625429,50.441108</coordinates></Point>
<Point>
<coordinates>30.625429,50.441104</coordinates></Point>
<Point>
<coordinates>30.625415,50.441074</coordinates></Point>
<Point>
<coordinates>30.625419,50.441104</coordinates></Point>
<Point>
<coordinates>30.625370,50.441085</coordinates></Point>
<Point>
<coordinates>30.625314,50.441051</coordinates></Point>
<Point>
<coordinates>30.625335,50.441066</coordinates></Point>
<Point>
<coordinates>30.625667,50.441024</coordinates></Point>
<Point>
<coordinates>30.625587,50.441005</coordinates></Point>
<Point>
<coordinates>30.625207,50.440696</coordinates></Point>
<Point>
<coordinates>30.625137,50.440738</coordinates></Point>
<Point>
<coordinates>30.625299,50.440345</coordinates></Point>
<Point>
<coordinates>30.625938,50.440605</coordinates></Point>
</Placemark>
</kml>
Command is completed
Я вам помогу выходите на связь.
Недавно на форуме журнала доктора Добба прочитал в свежих комментариях к тексту программы - "Ребята, успокойтесь, статья была написана 16 лет назад"
Arduino и Raspberry Pi постороены на совершенно разных микропроцессорах/микроконтроллерах, несовместимых на уровне команд и очень разные по вычислительной мощности - поэтому, конечно, какую-то часть модулей можно подключать к обоим платам - датчики, реле, джойстики и т.д., - то, что не требовательно к ресурсам. Но вот если камеры прекрасно тянет Raspberry Pi, то для Ардуино такие примочки недостижимы, из-за малых объемов памяти в Ардуино и ее скорости. Да и странно было бы существование поклонников Raspberry Pi, тратящих на нее десятки долларов, если бы то же самое можно было делать на Ардуино стоимостью пару баксов.
Для домашней метеостанции я бы порекомендовал сразу посмотреть в сторону wifi модуля ESP8266 - его удобно использовать и с Ардуино и без него (у него аналогичный встроенный микроконтроллер) - он сам коннектится на домашний роутер (в интернет) - и появляется возможность транслировать данные погоды в мир ( я использовал narodmon.ru - глянь прямо там, есть ссылки на железки), можно наоборот из инета читать погоду с погодных сайтов через Json и выводить на экран, опять через сеть удобно данные о погоде со своих датчиков обрабатывать на чем-то - можно просто на компьютере. Автономно на Ардуино скучновато - ну есть текущие показания, ну и что. Греет не долго. Сайтов много по поиску, вот, например, для затравки.
Вот из скучных вариантов на Ардуино - что я делал - http://forum.arduino.ua/viewtopic.php?id=818
где отпечатать качественно я знаю,
или выточить с куска нержавейки ) , ( дорого, но красиво )принято )
я еще лодку не закончил ) принтер подождет...
Лодка, кстати, супер! Мне очень нравится. Плохо, что скоро совсем похолодает Придется с ванной выгонять всех резиновый уточек и зимой там тестировать
молодцы )
а маленький во что обошелся, а то я что то запутался ? в кекущем зоопарке принтеров )печатаете на заказ? мне б корпус для девасины что б крепился на планку пикатинни, (
еще не рисовал )
Маленький обошелся, наверно, до 50 долларов, а то и меньше.
Но просто он собирался - из того, что уже было -
блок питания от компьютера - очень дорого, но брал свой.
А так - порезка акрила - не помню точно, с материалом кажется 250 грн была,
по принтеру - электроника (Ардуино Мега + Шилд Polulu - долларов 20),
Ну экструдер баксов 5 и шаговик один - со старого винчестера советского.
На разборку на разиобазаре купил старые DVD приводы - где по 10 грн брал, где по 50 грн.
В общем, не очень затратно - я на его основе просто хотел понять, как работает, как настраивается.
Идея себя не очень оправдала - потому что оси, построенные на шаговиках от DVD не очень хорошо под нагрузкой себя ведут - довольно часто проскакивает, сдвигается. Все время возня, что-то подправить, что-то подстроить...
А потом собрал Graber - это уже по накатанной, как конструктор .
Делать на заказ не буду - качество никакое, если на оружие что цеплять - так есть в Киеве много фирм, которые печатают на качественных принтерах, с очень тоненькой и ровненькой печатью совершенно недорого. Я сам много заказывал поначалу.
Кажется, я какие-то крепления для планки видел на
http://thingiverse.com/ - можно там посмотреть, по поиску Picatinny rail
привет
http://myshop.biz.ua/index.php?route=pr … duct_id=55
печатаете? или только в планах?
Привет! Печатаю. Любительски. Любительски - потому что не хватает терпения отстроить все, чтобы более качественная печать была - видно по картинкам, что не высокохудожественные работы получаются, но как механические объекты очень прочные.
Сделал два принтера - сначала маленький, потом Graber i3
Ну и раз начал хвастаться хозяйством - еще сделал лазерный гравер, в корпусе, аналогичном маленькому 3D принтеру, и ЧПУ станок, который уже несколько лет в состоянии - что-то можно делать, но показывать стыдно:
Продающийся копеешный радиомодуль em5807m с цифровым управлением по шине i2c я сначала выпаял из поломанного радиоприемника, а подом подкупил еще в Китае. Для управления модулем использовал Ардуино, чтобы выводить частоту настройки использовал дисплейный модуль с 4-я цифрами, тоже программирующийся по шине.
Приемник был смонтирован в корпусе поломанного аналогового приемника с часами (или наоборот).http://forum.arduino.ua/ В корпусе пригодились кнопки - две я задействовал на управление - выбор радиостанции из списка предустановленных в программе.
Картинки радиоприемника (извиняюсь за качество - использован модуль усилителя звука, Arduino Mini Pro, модуль дисплея tm1637, FM модуль RDA5807M).
Распиновка модуля следующая:
Шина I2C это пины 6 и 7 радиомодуля, они подключены к A4 A5 Ардуино, 2 и 3 контакт радиомодуля - выходы звуковые, один из них подключается к модулю усилителя звука.
Для подключения к ардуино используется следующая коммутация (только дисплейный модуль я использовал другой):
Пример кода для создания приемника на основе чипа 5807 и LED модуля tm1637 для индикации частоты приема.
Код рабочий, частоты настроены для Киева:
// Programm: fm_radio_module_em5807m_rev100.ino
// Language: Arduinio C++
// Hardware: Arduino Nano 3.0 + EM5807M module with RDA5807M Chip.
// Version: 1.00
// Autor: www.5v.ru
// Link: www.5v.ru/start/em5807m-arduino-nano-30.htm
/*
92.4 Ретро FM Oldies
92.8 Europa Plus Украина CHR
93.8 Бизнес Радио AC
94.2 Радио Ренессанс Contemporary Jazz
95.2 Радио Дача AC
95.6 Джем FM Rock
96.0 Эра FM News/Talk
96.4 Хит FM Hot AC/AC
96.8 DJFM Dance
98.0 Радіо Київ News/Talk, AC
98.5 Русское Радио Украина Russian Top 40
99.0 Radio Nostalgie Gold Hits/Oldies
99.4 Радио Next
100.0 Гала Радио Hot AC
100.5 Народное Радио -
101.1 Super Radio Hot AC
101.5 MusicРадио Easy Listening
101.9 Радио Шансон Шансон
102.5 Просто Ради.О AAA/Hot AC
103.1 Люкс FM Hot AC
103.6 Radio ROKS Rock
104.0 Радио Шарманка CHR/Top 40
104.6 Радио 24 AC
105.0 1-й канал НРУ
Радио «Промінь» News/Talk
105.5 Стильное радио Перец FM Top 40
106.0 Голос Столицы News, Gold Hits
106.5 Kiss FM Dance
107.0 Европа Плюс Киев AC
107.4 Авторадио Украина AC
107.9 Наше Радио AC
*/
#include "TM1637.h"
#include <Wire.h> // I2C-Library
#define CLK 13//pins definitions for TM1637 and can be changed to other ports
#define DIO 12
const int buttonPinMax = 9; // the number of the pushbutton pin
const int buttonPinMin = 8; // the number of the pushbutton pin
double f_ini=103.6; // Стартовая частота настройки приемника. (Изменяем на нужную).
// variables will change:
int buttonStateMax = 0; // variable for reading the pushbutton status
int buttonStateMin = 0; // variable for reading the pushbutton status
int Station=21;
TM1637 tm1637(CLK,DIO);
void setup() // Инициализация.
{
// initialize the pushbutton pin as an input:
pinMode(buttonPinMax, INPUT);
pinMode(buttonPinMin, INPUT);
tm1637.init();
tm1637.set(BRIGHT_TYPICAL);//BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7;
Wire.begin(); // Инициализация двухпроводной шины I2C.
setFrequency(f_ini); // Вызываем фукнкцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
}
void loop() // Основной цикл программы
{
// Здесь можем написать нашу самую лучшую программу, которая будет работать так как нам нужно.
buttonStateMax = digitalRead(buttonPinMax);
if (buttonStateMax == HIGH)
{
// turn LED on:
Station = Station + 1;
if (Station >=31) {Station = 1;};
ChangeStation ( Station);
DisplayStation (f_ini);
delay (1000);
}
buttonStateMin = digitalRead(buttonPinMin);
if (buttonStateMin == HIGH)
{
// turn LED on:
Station = Station - 1;
if (Station <1) {Station = 30;};
ChangeStation ( Station);
DisplayStation (f_ini);
delay (1000);
}
}
void ChangeStation (int Station)
{
switch (Station) {
case 1:
//do something when var equals 1
f_ini=92.4;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 2:
//do something when var equals 2
f_ini=92.8;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 3:
//do something when var equals 2
f_ini=93.8;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 4:
//do something when var equals 2
f_ini=94.2;
setFrequency(f_ini); // Вызываем фукнкцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 5:
//do something when var equals 2
f_ini=95.2;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 6:
//do something when var equals 2
f_ini=95.6;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 7:
//do something when var equals 2
f_ini=96.0;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 8:
//do something when var equals 2
f_ini=96.4;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 9:
//do something when var equals 2
f_ini=96.8;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 10:
//do something when var equals 2
f_ini=98.0;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 11:
//do something when var equals 2
f_ini=98.5;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 12:
//do something when var equals 2
f_ini=99.0;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 13:
//do something when var equals 2
f_ini=99.4;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 14:
//do something when var equals 2
f_ini=100.0;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 15:
//do something when var equals 2
f_ini=100.5;
setFrequency(f_ini); // Вызываем фукнкцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 16:
//do something when var equals 2
f_ini=101.1;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 17:
//do something when var equals 2
f_ini=101.5;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 18:
//do something when var equals 2
f_ini=101.9;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 19:
//do something when var equals 2
f_ini=102.5;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 20:
//do something when var equals 2
f_ini=103.1;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 21:
//do something when var equals 2
f_ini=103.6;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 22:
//do something when var equals 2
f_ini=104.0;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 23:
//do something when var equals 2
f_ini=104.6;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 24:
//do something when var equals 2
f_ini=105.0;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 25:
//do something when var equals 2
f_ini=105.5;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 26:
//do something when var equals 2
f_ini=106.0;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 27:
//do something when var equals 2
f_ini=106.5;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 28:
//do something when var equals 2
f_ini=107.0;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 29:
//do something when var equals 2
f_ini=107.4;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
case 30:
//do something when var equals 2
f_ini=107.9;
setFrequency(f_ini); // Вызываем функцию загрузки частоты настройки в модуль EM5807M.
DisplayStation (f_ini);
break;
default:
// if nothing else matches, do the default
// default is optional
break;
}
}
void DisplayStation (double Freq)
{
int8_t ListDisp[4];
ListDisp[0] = ((int)Freq/100) % 10;
ListDisp[1] = ((int)Freq/10) % 10;
ListDisp[2] = ((int)Freq/1) % 10;
ListDisp[3] = ((int)(Freq*10)) % 10;
tm1637.display(0,ListDisp[0]);
tm1637.display(1,ListDisp[1]);
tm1637.display(2,ListDisp[2]);
tm1637.display(3,ListDisp[3]);
}
void setFrequency(double fmhz) // Функция загрузки частоты настройки в модуль EM5807M.
{
int frequencyB = 4 * (fmhz * 1000000 + 225000) / 32768;
char frequencyH = frequencyB >> 8; // Старший байт.
char frequencyL = frequencyB & 0XFF; // Накладываем маску 0xFF на младший байт.
Wire.beginTransmission(0x60); // Адрес чипа RDA5807M
Wire.write(frequencyH); // Старший байт.
Wire.write(frequencyL); // Младший байт.
Wire.write(0xB8); // 1011 1000 =Стерео
Wire.write(0x10); // 0001 0000
Wire.write((byte)0x00); //
Wire.endTransmission(); // формируем I2C-Stop.
}
BMP180 ST7735 Arduino
Для создания небольшой домашней метеостанции был использован датчик давления и температуры BMP180, для вывода информации использовался дисплей TFT ST7735 и Arduino Mini Pro. Само устройство было помещено в коробочку для визиток из оргстекла.
В примере кода, который идет ниже по тексту, использовались следующие коммутации:
Дисплей подключен к пинам Ардуино так (cs к пину 10, dc к пину 9, rst к 8, gnd и power (3В!!!) дисплея к сответствующим выводам питания).
/**********************************************************
Bosch Pressure Sensor BMP085 / BMP180 readout routine
for the Arduino platform.
Compiled by Leo Nutz
[url=http://www.ALTDuino.de]www.ALTDuino.de[/url]
**********************************************************/
// 0.0075006375541921
#include <Wire.h>
#include "Barometer.h"
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
float temperature;
float pressure;
float atm;
float altitude;
Barometer myBarometer;
#define cs 10
#define dc 9
#define rst 8 // you can also connect this to the Arduino reset
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);
void setup()
{
Wire.begin(); // Activate I2C
Serial.begin(9600); // Set up serial port
myBarometer.init(); // Initialize baro sensor variables
delay(100);
tft.initR(INITR_BLACKTAB); // initialize a ST7735S chip, black tab
tft.fillScreen(ST7735_BLACK);
tft.setRotation(3);
}
void loop()
{
ShowInfo ();
}
void ShowInfo ()
{
temperature = myBarometer.bmp085GetTemperature(myBarometer.bmp085ReadUT()); //Get the temperature, bmp085ReadUT MUST be called first
pressure = myBarometer.bmp085GetPressure(myBarometer.bmp085ReadUP())*0.0075006375541921;//Get the pressure
altitude = myBarometer.calcAltitude(pressure); //Uncompensated caculation - in Meters
atm = pressure / 101325;
Serial.print("Temperature: ");
Serial.print(temperature, 2); //display 2 decimal places
Serial.println("deg C");
Serial.print("Pressure: ");
Serial.print(pressure, 0); //whole number only.
Serial.println(" mmHg");
Serial.print("Ralated Atmosphere: ");
Serial.println(atm, 4); //display 4 decimal places
Serial.print("Altitude: ");
Serial.print(altitude, 2); //display 2 decimal places
Serial.println(" m");
Serial.println();
delay(1000); //wait a second and get values again.
tft.fillRect (0,0, 160, 128,ST7735_BLACK);
tft.setTextWrap(true);
tft.setTextColor(ST7735_RED);
tft.setTextSize(3);
tft.setCursor(0, 0);
tft.println("Hello!");
tft.setTextColor(ST7735_BLUE);
tft.setTextSize(2);
tft.println("Temperature:");
tft.setTextSize(2);
tft.setTextColor(ST7735_YELLOW);
tft.print(temperature, 2);
tft.println(" C");
tft.setTextColor(ST7735_GREEN);
tft.setTextSize(2);
tft.println("Pressure: ");
tft.setTextColor(ST7735_CYAN);
tft.setTextSize(2);
tft.print(pressure, 2);
tft.println(" mmHg");
delay(5000);
// Delay between each readout
tft.setTextColor(ST7735_GREEN);
tft.setCursor(0, 20);
tft.setTextSize(12);
tft.fillRect (0,0, 160, 128,ST7735_BLACK);
tft.println(temperature, 0);
delay(2000);
tft.setTextColor(ST7735_WHITE);
tft.setTextSize(8);
tft.setCursor(0, 40);
tft.fillRect (0,0, 160, 128,ST7735_BLACK);
tft.println(pressure, 0);
delay(2000);
testfillcircles(5, ST7735_BLUE);
testdrawcircles(5, ST7735_WHITE);
delay(1000);
}
void testfillcircles(uint8_t radius, uint16_t color) {
for (int16_t x=radius; x < tft.width(); x+=radius*2) {
for (int16_t y=radius; y < tft.height(); y+=radius*2) {
tft.fillCircle(x, y, radius, color);
}
}
}
void testdrawcircles(uint8_t radius, uint16_t color) {
for (int16_t x=0; x < tft.width()+radius; x+=radius*2) {
for (int16_t y=0; y < tft.height()+radius; y+=radius*2) {
tft.drawCircle(x, y, radius, color);
}
}
}
Поскольку дисплейные модули изначально продаются, в большинстве случаев, с SD или microSD картоприемником, первым их применением у меня стало создание фоторамок.
(На самом деле, это у меня было из подсознания - подаренная девушкой покупная рамка успешно взорвалась после моей попытки установить внутрь аккумулятор с плохим контроллером заряда).
На основе модуля QVGA TFT display 320x240 ili9340 собрана такая фоторамка
Я использовал часы реального времени, Arduino Mini Pro, батарейный модуль, кнопку питания и сам дисплейный модуль
Как всегда, при работе с дисплейными модулями, самое сложное - подобрать хорошую, годную библиотеку, мне помогли библиотеки Adafruit_ILI9340.h и Adafruit_GFX.h.
Ниже приведен код:
/*
* Commands:
* T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99) - T(sec)(min)(hour)(dayOfWeek)(dayOfMonth)(month)(year) -
* T - Sets the date of the RTC DS1307 Chip.
*T0007002210115
* T004519
* Example to set the time for 25-Jan-2012 @ 19:57:11 for the 4 day of the week, use this command - T1157194250112
* Q(1-2) - (Q1) Memory initialization (Q2) RTC - Memory Dump
* R - Read/display the time, day and date
*/
#include <Adafruit_GFX.h> // Core graphics library
#include "Adafruit_ILI9340.h" // Hardware-specific library
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
#include <SPI.h>
//#if defined(__SAM3X8E__)
// #undef __FlashStringHelper::F(string_literal)
// #define F(string_literal) string_literal
//#endif
// TFT display and SD card will share the hardware SPI interface..
#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 10
#define SD_CS 6
#define DS1307_I2C_ADDRESS 0x68 // This is the I2C address
// Arduino version compatibility Pre-Compiler Directives
#if defined(ARDUINO) && ARDUINO >= 100 // Arduino v1.0 and newer
#define I2C_WRITE Wire.write
#define I2C_READ Wire.read
#else // Arduino Prior to v1.0
#define I2C_WRITE Wire.send
#define I2C_READ Wire.receive
#endif
// Global Variables
byte zero;
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
byte test;
int command = 0; // This is the command char, in ascii form, sent from the serial port
int i;
long previousMillis = 0; // will store last time Temp was updated
RTC_DS1307 rtc;
Adafruit_ILI9340 tft = Adafruit_ILI9340(TFT_CS, TFT_DC, TFT_RST);
File dir;
void setup(void) {
Serial.begin(9600);
Wire.begin();
tft.begin();
rtc.begin();
if (! rtc.isrunning()) {
Serial.println(F("RTC is NOT running!"));
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(__DATE__, __TIME__));
}
//
Serial.print(F("Initializing SD card..."));
if (!SD.begin(SD_CS)) {
Serial.println(F("failed!"));
return;
}
Serial.println(F("OK!"));
printtime ();
delay (1000);
freeMem();
// CheckCmd();
}
void loop() {
File dir=SD.open("/");
dir.rewindDirectory();
while (true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
Serial.println(F("**nomorefiles**"));
// break;
dir.rewindDirectory();
}
// Print the 8.3 name
Serial.print(entry.name());
// Recurse for directories, otherwise print the file size
if (entry.isDirectory()) {
Serial.println(F("/"));
}
else{
// files have sizes, directories do not
Serial.print(F("\t\t"));
Serial.println(entry.size(), DEC);
bmpDraw(entry.name(),0,0);
delay(3000);
}
entry.close();
printtime ();
}
dir.rewindDirectory();
}
uint16_t freeMem() {
char top;
extern char *__brkval;
extern char __bss_end;
Serial.println( __brkval ? &top - __brkval : &top - &__bss_end);
}
#define BUFFPIXEL 20
void bmpDraw(char *filename, uint8_t x, uint8_t y) {
File bmpFile;
int bmpWidth, bmpHeight; // W+H in pixels
uint8_t bmpDepth; // Bit depth (currently must be 24)
uint32_t bmpImageoffset; // Start of image data in file
uint32_t rowSize; // Not always = bmpWidth; may have padding
uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
boolean goodBmp = false; // Set to true on valid header parse
boolean flip = true; // BMP is stored bottom-to-top
int w, h, row, col;
uint8_t r, g, b;
uint32_t pos = 0, startTime = millis();
if((x >= tft.width()) || (y >= tft.height())) return;
Serial.println();
Serial.print(F("Loading image '"));
Serial.print(filename);
Serial.println('\'');
// Open requested file on SD card
if ((bmpFile = SD.open(filename)) == NULL) {
Serial.print(F("File not found"));
return;
}
// Parse BMP header
if(read16(bmpFile) == 0x4D42) { // BMP signature
Serial.print(F("File size: ")); Serial.println(read32(bmpFile));
(void)read32(bmpFile); // Read & ignore creator bytes
bmpImageoffset = read32(bmpFile); // Start of image data
Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
// Read DIB header
Serial.print(F("Header size: ")); Serial.println(read32(bmpFile));
bmpWidth = read32(bmpFile);
bmpHeight = read32(bmpFile);
if(read16(bmpFile) == 1) { // # planes -- must be '1'
bmpDepth = read16(bmpFile); // bits per pixel
Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
goodBmp = true; // Supported BMP format -- proceed!
Serial.print(F("Image size: "));
Serial.print(bmpWidth);
Serial.print(F("x"));
Serial.println(bmpHeight);
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * 3 + 3) & ~3;
// If bmpHeight is negative, image is in top-down order.
// This is not canon but has been observed in the wild.
if(bmpHeight < 0) {
bmpHeight = -bmpHeight;
flip = false;
}
// Crop area to be loaded
w = bmpWidth;
h = bmpHeight;
if((x+w-1) >= tft.width()) w = tft.width() - x;
if((y+h-1) >= tft.height()) h = tft.height() - y;
// Set TFT address window to clipped image bounds
tft.setAddrWindow(x, y, x+w-1, y+h-1);
for (row=0; row<h; row++) { // For each scanline...
// Seek to start of scan line. It might seem labor-
// intensive to be doing this on every line, but this
// method covers a lot of gritty details like cropping
// and scanline padding. Also, the seek only takes
// place if the file position actually needs to change
// (avoids a lot of cluster math in SD library).
if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
else // Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize;
if(bmpFile.position() != pos) { // Need seek?
bmpFile.seek(pos);
buffidx = sizeof(sdbuffer); // Force buffer reload
}
for (col=0; col<w; col++) { // For each pixel...
// Time to read more pixel data?
if (buffidx >= sizeof(sdbuffer)) { // Indeed
bmpFile.read(sdbuffer, sizeof(sdbuffer));
buffidx = 0; // Set index to beginning
}
// Convert pixel from BMP to TFT format, push to display
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
tft.pushColor(tft.Color565(r,g,b));
} // end pixel
} // end scanline
Serial.print(F("Loaded in "));
Serial.print(millis() - startTime);
Serial.println(F(" ms"));
} // end goodBmp
}
}
bmpFile.close();
if(!goodBmp) Serial.println(F("BMP format not recognized."));
}
// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.
uint16_t read16(File f) {
uint16_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read(); // MSB
return result;
}
uint32_t read32(File f) {
uint32_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read();
((uint8_t *)&result)[2] = f.read();
((uint8_t *)&result)[3] = f.read(); // MSB
return result;
}
void printtime () {
DateTime now = rtc.now();
// tft.fillScreen(ILI9340_BLACK);
tft.setTextColor (ILI9340_RED,ILI9340_BLACK);
tft.setTextSize (4);
tft.setCursor(0,00);
tft.print(now.year(), DEC);
tft.print(F("/"));
if (now.month() < 10)
tft.print("0");
tft.print(now.month(), DEC);
tft.print(F("/"));
if (now.day() < 10)
tft.print(F("0"));
tft.print(now.day(), DEC);
tft.println(F(""));
tft.setCursor(0,280);
tft.setTextColor (ILI9340_GREEN,ILI9340_BLUE);
tft.setTextSize (5);
if (now.hour() < 10)
tft.print(F("0"));
tft.print(now.hour(), DEC);
tft.print(F(":"));
if (now.minute() < 10)
tft.print(F("0"));
tft.print(now.minute(), DEC);
tft.print(F(":"));
if (now.second() < 10)
tft.print(F("0"));
tft.print(now.second(), DEC);
tft.println();
delay(5000);
}
void CheckCmd() {
if (Serial.available()) { // Look for char in serial que and process if found
command = Serial.read();
if (command == 84 || command == 116) { //If command = "Tt" Set Date
setDateDs1307();
}
Serial.println(command); // Echo command CHAR in ascii that was sent
}
command = 0; // reset command
delay(100);
}
void setDateDs1307()
{
second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.
minute = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
hour = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
dayOfWeek = (byte) (Serial.read() - 48);
dayOfMonth = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
month = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
year= (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
Wire.beginTransmission(DS1307_I2C_ADDRESS);
I2C_WRITE(zero);
I2C_WRITE(decToBcd(second) & 0x7f); // 0 to bit 7 starts the clock
I2C_WRITE(decToBcd(minute));
I2C_WRITE(decToBcd(hour)); // If you want 12 hour am/pm you need to set
// bit 6 (also need to change readDateDs1307)
I2C_WRITE(decToBcd(dayOfWeek));
I2C_WRITE(decToBcd(dayOfMonth));
I2C_WRITE(decToBcd(month));
I2C_WRITE(decToBcd(year));
Wire.endTransmission();
}
// Gets the date and time from the ds1307 and prints result
void getDateDs1307()
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
I2C_WRITE(zero);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
second = bcdToDec(I2C_READ() & 0x7f);
minute = bcdToDec(I2C_READ());
hour = bcdToDec(I2C_READ() & 0x3f); // Need to change this if 12 hour am/pm
dayOfWeek = bcdToDec(I2C_READ());
dayOfMonth = bcdToDec(I2C_READ());
month = bcdToDec(I2C_READ());
year = bcdToDec(I2C_READ());
}
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
Сторінки 1