Управление камерой, приборами и данные с датчиков на экране телевизора

arduino91-1

Устройство на Arduino, используется микросхема max7456.

Это OSD (on screen display) монохромный
256 зарезервированных символов
TSSOP 28 – корпус
Подключается к телевизору по входам «тюльпан».

Возможности:
— просмотр изображения с камеры
— управление камерой (вверх-вниз, влево-вправо)
— отображение данных с датчиков (температура, влажность воздуха, давление)
— управление приборами (RGB лента, новогодняя лампа-ночник RGB, прожектор на входе, управление открыванием входной двери)
— по срабатыванию датчика движения — переключение телевизора на изображение с видеокамеры

Управляется все пультом с используемого телевизора. Сначала предисловие, почему возникла необходимость данного устройства. На лампу и RGB-ленту постоянно неизвестно где пульт, к камере доступ с компа по WEB-интерфейсу, что не очень удобно, если хочешь посмотреть кто пришел. Если все будет на экране телевизора и управляться пультом с этого же телевизора, конечно же упростит пользование данными приборами. Конечно и пульт от телевизора теряется, но гораздо реже.

Микросхема max7456 имелась лишняя (покупал для платы OSD для радиоуправляемого автомобиля, но пришла бракованная плата GPS и пока проект откладывается)

Вот схема устройства (нет пока датчика движения и микросхемы часов D1307)

arduino91-2

И скетч для Arduino (неполный — еще не пришли датчик движения и микросхема часов DS1307)

Используются библиотеки

MAX7456 — вывод символов через max7456;

IRremote — получение и отправка ИК;

Servo — для управления сервоприводами поворота камеры;

OneWire — для работы с датчиками температуры DS18B20;

DHT — для работы с датчиком DH11 (измерение влажности воздуха)

BMP085 — для работы с датчиком BMP085 (атмосферное давление)

#define DATAOUT 11//MOSI
#define DATAIN 12//MISO
#define SPICLOCK 13//sck
#define MAX7456SELECT 10//ss
#define VSYNC 0x02// INT0

#define DMM_reg 0x04
#define DMAH_reg 0x05
#define DMAL_reg 0x06
#define DMDI_reg 0x07
#define VM0_reg 0x00
#define VM1_reg 0x01

#define VIDEO_BUFFER_DISABLE 0x01
#define MAX7456_RESET 0x02
#define VERTICAL_SYNC_NEXT_VSYNC 0x04
#define OSD_ENABLE 0x08
#define SYNC_MODE_AUTO 0x00
#define SYNC_MODE_INTERNAL 0x30
#define SYNC_MODE_EXTERNAL 0x20
#define VIDEO_MODE_PAL 0x40
#define VIDEO_MODE_NTSC 0x00

#define BLINK_DUTY_CYCLE_50_50 0x00
#define BLINK_DUTY_CYCLE_33_66 0x01
#define BLINK_DUTY_CYCLE_25_75 0x02
#define BLINK_DUTY_CYCLE_75_25 0x03

#define BLINK_TIME_0 0x00
#define BLINK_TIME_1 0x04
#define BLINK_TIME_2 0x08
#define BLINK_TIME_3 0x0C

#define BACKGROUND_BRIGHTNESS_0 0x00
#define BACKGROUND_BRIGHTNESS_7 0x10
#define BACKGROUND_BRIGHTNESS_14 0x20
#define BACKGROUND_BRIGHTNESS_21 0x30
#define BACKGROUND_BRIGHTNESS_28 0x40
#define BACKGROUND_BRIGHTNESS_35 0x50
#define BACKGROUND_BRIGHTNESS_42 0x60
#define BACKGROUND_BRIGHTNESS_49 0x70

#define BACKGROUND_MODE_GRAY 0x40

#define CLEAR_display 0x04
#define CLEAR_display_vert 0x06
#define END_string 0xff
#define ENABLE_display 0x08
#define ENABLE_display_vert 0x0c
#define MAX7456_reset 0x02
#define DISABLE_display 0x00

#define WHITE_level_80 0x03
#define WHITE_level_90 0x02
#define WHITE_level_100 0x01
#define WHITE_level_120 0x00

#define MAX_screen_size 390
#define MAX_screen_rows 16

byte spi_junk, eeprom_junk;
int x;

//***************************
struct MENU // структура меню
{
char* name1[27]; // наименование
int y[27];
int x[27];
int activ[27];
int pos1; // позиция меню
char bottom2[100];
int offbottom2;
};
MENU MENU1={
{"Камера","\xD6","\xD2","\xD5","\xD7","00",
"Датчики","Выкл",
"Прибор","Ч","Б","К","О","С","Г","З","Б",
"Ч","Б","К","О","С","Г","З","Б",
"Выкл","00:00" },
{2,4,5,4,5,4,10,13,19,19,20,21,22,23,24,25,26,19,20,21,22,23,24,25,26,19,22},
{1,2,2,3,3,4,1, 6, 1, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 7, 13},
{1,0,0,0,0,0,1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
0," ",0};

struct MYDATA // структура меню
{
int servo_ud; // положение камеры up-down
int servo_lr; // положение камеры left-right
float t1; // значение t1
float t2; // значение t2
float h1; // значение h1 - относительная влажность
float p1; // значение p1 - давление
int dd; // датчик движения Выкл-Вкл
int posl1; // лампа (0-7)
int posl2; // лента (0-7)
int posp1; // прожектор
};
MYDATA MYDATA1={0,0,0.0,0.0,0.0,0.0,0,0,0,0};

#include "IRremote.h"
int RECV_PIN=2;
IRrecv irrecv(RECV_PIN);
IRsend irsend;
//decode_results results;
unsigned long ir_dt, old_ir;
long ir_kod;
unsigned long ir_time1, ir_time2;
#define B_LEFT1 0x11
#define B_LEFT2 0x811
#define B_RIGHT1 0x10
#define B_RIGHT2 0x810
#define B_OK1 0x25
#define B_OK2 0x825
#define B_CLEARMENU1 0x37
#define B_CLEARMENU2 0x837

#include "Servo.h"
Servo camera_hor,camera_vert;

#include "OneWire.h"
OneWire ds(8); // on pin 8
byte my_addr[3][8]={{0x28,0x67,0xE5,0xC7,2,0,0,0xA0},
{0x28,0x94,0xB4,0x65,4,0,0,0xAC},
{0x28,0xF6,0x98,0xBA,2,0,0,0x92}};
#include "Wire.h"
#include "BMP085.h"
BMP085 dps = BMP085();
long Pressure085 = 0, Altitude085 = 0;

#include "DHT.h"

#define DHTTYPE DHT11 // DHT 11
DHT dht(7, DHTTYPE);
float dh1;
//////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(9600);
Serial.flush();
Serial.println("setup");

pinMode(MAX7456SELECT,OUTPUT);
digitalWrite(MAX7456SELECT,HIGH);

pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK,OUTPUT);
pinMode(VSYNC, INPUT);

SPCR = (1<0) { Serial.println(ir_kod,HEX); change_pos_menu(ir_kod); ir_kod=0; } delay(100); } ////////////////////////////////////////////////////////////// byte spi_transfer(volatile byte data) { SPDR = data; while (!(SPSR & (1<> 8;
char_address_lo = linepos;

settings = B00000001;

if (blink) {
settings |= (1 << 4); } if (invert){ settings |= (1 << 3); } digitalWrite(MAX7456SELECT,LOW); spi_transfer(DMM_reg); spi_transfer(settings); spi_transfer(DMAH_reg); spi_transfer(char_address_hi); spi_transfer(DMAL_reg); spi_transfer(char_address_lo); while(s[local_count]!='\0') { screen_char = s[local_count]; if(screen_char != 208 && screen_char != 209) { spi_transfer(DMDI_reg); spi_transfer(screen_char); } local_count++; } spi_transfer(DMDI_reg); spi_transfer(END_string); spi_transfer(DMM_reg); spi_transfer(B00000000); digitalWrite(MAX7456SELECT,HIGH); } // получить код переданный с ИК пульта void get_ir_kod() { decode_results results; detachInterrupt(0); // отключить прерывание 0 if (irrecv.decode(&results)) { if (results.value > 0 && results.value < 0xFFFFFFFF) { ir_dt = results.value; ir_time2=millis(); if (ir_time2-ir_time1>400)
{ir_kod = ir_dt;ir_time1=ir_time2;}
else
ir_kod = 0;
}
irrecv.resume();
}
attachInterrupt(0, get_ir_kod, FALLING);
}
//
void show_menu()
{
for(int i=0;i<27;i++) { if(i==MENU1.pos1 && MENU1.activ[i]==1) OSD_write_to_screen(MENU1.name1[i],MENU1.y[i],MENU1.x[i], 1,1); else if(MENU1.activ[i]==1) OSD_write_to_screen(MENU1.name1[i],MENU1.y[i],MENU1.x[i], 0,0); } } // проверка на определенные для действий клавиши void change_pos_menu(long kod) { int newpos=0;int dd=1; if(kod==B_LEFT1 || kod==B_LEFT2) // уменьшить звуко { do { newpos=max(MENU1.pos1-dd,0);dd++; } while(MENU1.activ[newpos]<1); MENU1.pos1=newpos;} else if(kod==B_RIGHT1 || kod==B_RIGHT2) // увеличить звуко { do { newpos=min(MENU1.pos1+dd,26);dd++; } while(MENU1.activ[newpos]<1); MENU1.pos1=newpos;} else if(kod==B_OK1 || kod==B_OK2) // ok prg_ok(); else if(kod==B_CLEARMENU1 || kod==B_CLEARMENU2) // ok clear_menu2(); else ; Serial.println(MENU1.pos1); } // очистка всех подменю void clear_menu2() { MENU1.pos1=0; for(int i=0;i<27;i++) {MENU1.activ[i]=0; for(int j=2;j<8;j++) OSD_write_to_screen(" ", i, j, 0,0); } MENU1.activ[0]=1;MENU1.activ[6]=1; MENU1.activ[8]=1;MENU1.activ[26]=1; } // клавиша ok void prg_ok() {char c1[4];char dd[7]; switch(MENU1.pos1) { case 0 : // меню камера if(MENU1.activ[2]==1) { OSD_write_to_screen(" ",2,2,0,0); OSD_write_to_screen(" ",2,3,0,0); OSD_write_to_screen(" ",2,4,0,0); MENU1.activ[1]=0;MENU1.activ[2]=0;MENU1.activ[3]=0; MENU1.activ[4]=0;MENU1.activ[5]=0; } else { MENU1.activ[1]=1;MENU1.activ[2]=1;MENU1.activ[3]=1; MENU1.activ[4]=1;MENU1.activ[5]=1; } break; case 1 : // камера вниз MYDATA1.servo_ud=max(MYDATA1.servo_ud-10,-90); camera_vert.attach(5); camera_vert.write(MYDATA1.servo_ud+90); delay(500); camera_vert.detach(); Serial.print("down=");Serial.println(MYDATA1.servo_ud); break; case 2 : // камера вверх MYDATA1.servo_ud=min(MYDATA1.servo_ud+10,90); camera_vert.attach(5); camera_vert.write(MYDATA1.servo_ud+90); delay(500); camera_vert.detach(); Serial.print("up=");Serial.println(MYDATA1.servo_ud); break; case 3 : // камера влево MYDATA1.servo_lr=max(MYDATA1.servo_lr-10,-90); camera_hor.attach(4); camera_hor.write(MYDATA1.servo_lr+90); delay(500); camera_hor.detach(); Serial.print("left=");Serial.println(MYDATA1.servo_lr); break; case 4 : // "камера вправо" MYDATA1.servo_lr=min(MYDATA1.servo_lr+10,90); camera_hor.attach(4); camera_hor.write(MYDATA1.servo_lr+90); delay(500); Serial.print("right=");Serial.println(MYDATA1.servo_lr); camera_hor.detach(); break; case 5 : // "камера в 0" MYDATA1.servo_ud=0;MYDATA1.servo_lr=0; camera_hor.attach(4);camera_vert.attach(5); camera_hor.write(90);camera_vert.write(90); delay(500); camera_hor.detach();camera_vert.detach(); break; case 6 : // меню датчики if(MENU1.activ[7]==1) { OSD_write_to_screen(" ",10,2,0,0); OSD_write_to_screen(" ",10,3,0,0); OSD_write_to_screen(" ",10,4,0,0); OSD_write_to_screen(" ",10,5,0,0); OSD_write_to_screen(" ",10,6,0,0); MENU1.activ[7]=0; } else { MENU1.activ[7]=1; dtostrf(getMeteoData(2),0,2,dd); OSD_write_to_screen(dd,10,2,0,0); //sprintf(dd,"%f",getMeteoData(1)); dtostrf(getMeteoData(1),0,2,dd); OSD_write_to_screen(dd,10,3,0,0); Serial.print("dht="); detachInterrupt(0); delay(100); irsend.sendRC5(0xff,12); delay(1000); attachInterrupt(0, get_ir_kod, FALLING); dh1=dht.readHumidity(); Serial.println(dh1); dtostrf(dht.readHumidity(),0,0,dd); dd[3]=0x25;dd[4]=' ';dd[2]=' '; OSD_write_to_screen(dd,10,4,0,0); dps.getPressure(&Pressure085); dtostrf(Pressure085/133.3,0,2,dd); OSD_write_to_screen(dd,10,5,0,0); OSD_write_to_screen("ДД ",10,6,0,0); OSD_write_to_screen("Вкл ",13,6,0,0); irrecv.enableIRIn(); } break; case 7 : // датчик движения MYDATA1.dd=1-MYDATA1.dd; if(MYDATA1.dd==0) MENU1.name1[7]="Выкл"; else MENU1.name1[7]="Вкл "; send_ir_kod(0x01); send_ir_kod(0x838); break; case 8 : // меню приборы if(MENU1.activ[9]==1) { OSD_write_to_screen(" ",19,2,0,0); OSD_write_to_screen(" ",19,3,0,0); MENU1.activ[9]=0;MENU1.activ[10]=0; MENU1.activ[11]=0;MENU1.activ[12]=0;MENU1.activ[13]=0; MENU1.activ[14]=0;MENU1.activ[15]=0;MENU1.activ[16]=0; OSD_write_to_screen(" ",19,4,0,0); OSD_write_to_screen(" ",19,5,0,0); MENU1.activ[17]=0;MENU1.activ[18]=0; MENU1.activ[19]=0;MENU1.activ[20]=0;MENU1.activ[21]=0; MENU1.activ[22]=0;MENU1.activ[23]=0;MENU1.activ[24]=0; OSD_write_to_screen(" ",19,6,0,0); MENU1.activ[25]=0; OSD_write_to_screen(" ",19,7,0,0); } else { OSD_write_to_screen("Лампа",19,2,0,0); MENU1.activ[9]=1;MENU1.activ[10]=1; MENU1.activ[11]=1;MENU1.activ[12]=1;MENU1.activ[13]=1; MENU1.activ[14]=1;MENU1.activ[15]=1;MENU1.activ[16]=1; OSD_write_to_screen("Лента",19,4,0,0); MENU1.activ[17]=1;MENU1.activ[18]=1; MENU1.activ[19]=1;MENU1.activ[20]=1;MENU1.activ[21]=1; MENU1.activ[22]=1;MENU1.activ[23]=1;MENU1.activ[24]=1; OSD_write_to_screen("Прож",19,6,0,0); MENU1.activ[25]=1; OSD_write_to_screen(" ",19,7,0,0); } break; // лампа1 case 9 : // черный MYDATA1.posl1=0;send_ir_kod(0x1);break; case 10 : // белый MYDATA1.posl1=1;send_ir_kod(0x2);break; case 11 : // MYDATA1.posl1=2;send_ir_kod(0x2);break; case 12 : // MYDATA1.posl1=3;send_ir_kod(0x2);break; case 13 : // MYDATA1.posl1=4;send_ir_kod(0x2);break; case 14 : // MYDATA1.posl1=5;send_ir_kod(0x2);break; case 15 : // MYDATA1.posl1=6;send_ir_kod(0x2);break; case 16 : // MYDATA1.posl1=7;send_ir_kod(0x2);break; // лента светодиодная //0xDF,0x9F,0x5F,0xEF,0xAF,0x6F,0x1F,0xBF case 17 : // черный MYDATA1.posl2=0;send_ir_kod(0xBF);break; case 18 : // белый MYDATA1.posl2=1;send_ir_kod(0x1F);break; case 19 : // R MYDATA1.posl2=2;send_ir_kod(0xDF);break; case 20 : // RB MYDATA1.posl2=3;send_ir_kod(0x2);break; case 21 : // B MYDATA1.posl2=4;send_ir_kod(0x5F);break; case 22 : // BG MYDATA1.posl2=5;send_ir_kod(0x2);break; case 23 : // G MYDATA1.posl2=6;send_ir_kod(0x9F);break; case 24 : // RG MYDATA1.posl2=7;send_ir_kod(0x2);break; // прожектор case 25 : MYDATA1.posp1=1-MYDATA1.posp1; if(MYDATA1.posp1==0) MENU1.name1[25]="Выкл"; else MENU1.name1[25]="Вкл "; break; default: break; } sprintf(c1,"%d",abs(MYDATA1.servo_ud)); OSD_write_to_screen(" ",2,2,0,0);OSD_write_to_screen(" ",6,2,0,0); if(MYDATA1.servo_ud<0 && MENU1.activ[2]==1) {OSD_write_to_screen(c1,2,2,0,0);} else if(MYDATA1.servo_ud>0 && MENU1.activ[2]==1)
{OSD_write_to_screen(c1,6,2,0,0);}
else ;
sprintf(c1,"%d",abs(MYDATA1.servo_lr));
OSD_write_to_screen(" ",2,3,0,0);OSD_write_to_screen(" ",6,3,0,0);
if(MYDATA1.servo_lr<0 && MENU1.activ[2]==1) {OSD_write_to_screen(c1,2,3,0,0);} else if(MYDATA1.servo_lr>0 && MENU1.activ[2]==1)
{OSD_write_to_screen(c1,6,3,0,0);}
else ;
}
// Отправка ИК-кода
void send_ir_kod(long sendkod)
{
detachInterrupt(0);
delay(100);
irsend.sendRC5(sendkod,12);
delay(1000);
attachInterrupt(0, get_ir_kod, FALLING);
irrecv.enableIRIn();
Serial.print("sendkod=");Serial.println(sendkod,HEX);
}
// получение температуры датчика
float getMeteoData(int nn)
{
byte i;
byte present = 0;
byte data[12];
byte addr[8];
int Temp;
float fTemp;
char m0[5];
String str1="";

ds.reset();
ds.select(my_addr[nn-1]);
ds.write(0x44,1); // start conversion, with parasite power on at the end
delay(1000); // maybe 750ms is enough, maybe not

present = ds.reset();
ds.select(my_addr[nn-1]);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); } Temp=(data[1]<<8)+data[0];//take the two bytes from the response relating to temperature Temp=Temp;//divide by 16 to get pure celcius readout fTemp=Temp/16+(float(Temp%16))/16; MYDATA1.t2=fTemp; return fTemp; }

Проблемы, возникшие при написании скетча:
DHT отказывалась работать с IRremote (функция enableIRIn() занимает таймер, используемый библиотекой DHT), проблема решилась отключением на время получения с датчика DHT11 enableIRIn(), и включением после получения данных.

Управление с помощью пульта телевизора. Навигация влево-вправо (громкость), выбор (ОК), свернуть все подменю -(EYE/*)

Необходимо рассказать о прошивке символов микросхемы MAX7456. В памяти микросхемы уже имеются прошитые символы

arduino91-3

Необходимо перепрошить, чтобы были русские символы и некоторые специальные (стрелки).

Скачиваем библиотеку MAX7456. В библиотеке есть пример перепрошивки символов - UploadFont и несколько файлов .mcm с шрифтами для загрузки.

Запускаем программу Hiper Terminal, выбираем порт на котором сидит Ардуино, скорость порта 9600, управление потоком xon-xoff. В меню программы гипертерминал выбираем пункт send to file и указываем путь к файлу со шрифтом. Файл с русским шрифтом arduino1.mcm я взял на форуме http://www.compcar.ru/forum/showthread.php?t=6064. Символы такие (arduino1.png)

arduino91-5
arduino91-4
arduino91-6

2 comments

  1. В последнее время в связи с удешевлением электронных систем всё чаще применяются датчики со сложной обработкой сигналов, возможностями настройки и регулирования параметров и стандартным интерфейсом системы управления. Имеется определённая тенденция расширительной трактовки и перенесения этого термина на измерительные приборы, появившиеся значительно ранее массового использования датчиков, а также по аналогии — на объекты иной природы, например, биологические.

  2. ukR0zT uyyhcryqrpcz, [url=http://hfiaiexmiopw.com/]hfiaiexmiopw[/url], [link=http://fqzpwjmavnyx.com/]fqzpwjmavnyx[/link], http://gfjokdiwmipp.com/

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>