Авто. Температура снаружи и внутри, вывод на lcd1602, регулировка яркости подсветки при помощи фоторезистора
- Войдите на сайт для отправки комментариев
Здравствуйте товарищи программисты.
У меня старая машинка 97 года, которая неумеет измерять температуру. Решил что я всетаки хочу ее знать и хочу чтоб это выглядело хоть както прилично. Друг посоветовал ардуино, ну по незнанию я с ним конечно же согласился, отправился в алиэкспресс и заказал там 1х Arduino Nano, x2 Датчика DS18B20, х1 LCD 1602 дисплей в комплекте с I2C интерфейсом.
Не так давно дождался своей первой Arduino Nano ну и собственно незамедлительно приступил к изучению всего что подруку попалось на эту тему. Беспощадно тратя рабочее время вскоре я получил желаемый результат, оба датчика показывали мне свои показания на дисплее. Радостный и довольный пошел в машину тестировать свое "изобретение", датчики исправно показывали как минусовую так и плюсовую температуру. Единственным минусом стала чрезмерно высокая яркость дисплея в ночное время, аж пришлось глаза прищурить. Погуглил немного, нарвался на фоторезисторы. Благо у посоветовавшего мне ардуино друга нашлось пару штук, взял у него один, так как больше и ненужно было, вообщем теперь есть в наличии х1 Фоторезистрор порядка 50кОм при полной темноте.
Посмотрел на ардуинку утыканую припаяными проводами так что ничего не подсунуть, решил что надо немного поудобнее сделать свой первый отладочный агрегат. О бредбордах я и в помине не знал, так что попути решил изучить травление плат в дом.условиях. За часик-полтора ознакомился со Sprint Layout 5.0 ну и собствено пока ознакамливался начертил желаемую плату. Вытравил и собрал все на ней.
Немного помучался с показаниями фоторезистора выводимыми на lcd, но по своей глупости... спустя час вспомнил что lcd не удаляет символы самостоятельно и благополучно добавив пробел после вывода результата analogRead(0) получил наконец вменяемые цифры от 0 до 1013. Быстренько снял джампер отвечающий за подсветку с I2C интерфейса и подпаяв его к 10 цифровому порту, начал писать код. Написаный мной код не в какую не хотел регулировать подсветку дисплея, и даже не включал ее. На глаза попался коментарий о том кто в I2C интерфейсах заказаных с китая необходимо обязательно указывать включение подсветки lcd.backlight() после того как я ее добавил все благополучно заработало и функция analogWrite(BL,255) выставила мне желаемый результат. Дальше немного пораздумав написал топорный код для регулировки подсветки.
int PhCount = analogRead(0); PhCount = PhCount/4; if(PhCount > 255){ analogWrite(BL, 255); } else { if(PhCount < 40){ //минимальный уровень подсветки 40 analogWrite(BL, 40); } else { analogWrite(BL, PhCount); } }
Собственно говоря можно приступать к выбору места в машине под lcd, т.к. осталось собрать источник питания для ардуинки, вытравить более компактную схему, только для тех компонентов которые будут использованы. Распихать датчики по машине и все скомутировать. Пока буду заниматься всем этим, есть время подчистить код, т.к я более чем уверен что он плохо выглядит :)) На данный момент все это выглядит вот так:
Строка PhCount отображает текущее значение показаний фоторезистора деленное на 4. Собственно далее полный скетч для того чтобы меня забрасали тапками и помидорами:
//------------------------------------- Подключенные библиотеки --------------------------- #include <Wire.h> #include <LiquidCrystal_I2C.h> #include <OneWire.h> //------------------------------------- Дополнительные установки -------------------------- LiquidCrystal_I2C lcd(0x27,16,2); //задаем адрес LCD экрана 0x27, 16 символов, 2 строки int inTSensorConnectedPin = 4; int outTSensorConnectedPin = 5; OneWire ds1(inTSensorConnectedPin); OneWire ds2(outTSensorConnectedPin); float inTSensor; float outTSensor; int BL = 10; //------------------------------------- SETUP --------------------------------------------- void setup() { pinMode(BL, OUTPUT); Serial.begin(9600); //отправляем на монитор lcd.init(); // Инициализируем экран lcd.backlight(); analogWrite(BL, 255); lcd.clear(); lcd.setCursor(2, 0); lcd.print("Loading..."); lcd.setCursor(5, 1); lcd.print("ver. 1.99"); delay(1000); lcd.clear(); uint8_t box[]={0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F}; lcd.createChar(0,box); lcd.setCursor(2, 0); lcd.print("Loading..."); for(int i=0; i <= 15; i++){ lcd.setCursor(i, 1); lcd.write(0); delay(80); } delay(400); lcd.clear(); } //----------------------------------------- LOOP ------------------------------------------ void loop() { int PhCount = analogRead(0); PhCount = PhCount/4; if(PhCount > 255){ analogWrite(BL, 255); } else { if(PhCount < 40){ analogWrite(BL, 40); } else { analogWrite(BL, PhCount); } } uint8_t temp2[]={0x06,0x09,0x09,0x06,0x00,0x00,0x00,0x00}; //Отрисовка градусов Цельсия lcd.createChar(1,temp2); float out_temp = getOutsideTemp(); lcd.setCursor(0,0); lcd.print("Out:"); lcd.setCursor(4, 0); lcd.print(out_temp, 0); lcd.write(1); lcd.print(" "); float in_temp = getInsideTemp(); lcd.setCursor(9,0); lcd.print("In:"); lcd.setCursor(12, 0); lcd.print(in_temp, 0); lcd.write(1); lcd.print(" "); lcd.setCursor(0,1); lcd.print("PhCount: "); lcd.print(PhCount); lcd.print(" "); } float getOutsideTemp() { byte data[12]; byte addr[8]; if ( !ds2.search(addr)) { lcd.setCursor(0, 0); lcd.print("NO more addrss!"); ds2.reset_search(); return -1001; } if ( OneWire::crc8( addr, 7) != addr[7]) { lcd.setCursor(0, 0); lcd.print("CRC is not valid!"); return -1002; } if ( addr[0] != 0x10 && addr[0] != 0x28) { lcd.setCursor(0, 0); lcd.print("NOT recognizd!"); return -1003; } ds2.reset(); ds2.select(addr); ds2.write(0x44,1); byte present = ds2.reset(); ds2.select(addr); ds2.write(0xBE); for (int i = 0; i < 9; i++) { data[i] = ds2.read(); } ds2.reset_search(); byte MSB = data[1]; byte LSB = data[0]; float TRead = ((MSB<<8) | LSB); float Temperature = TRead / 16; return Temperature; } float getInsideTemp() { byte data[12]; byte addr[8]; if ( !ds1.search(addr)) { lcd.setCursor(0, 1); lcd.print("NO more addrss!"); ds1.reset_search(); return -1001; } if ( OneWire::crc8( addr, 7) != addr[7]) { lcd.setCursor(0, 1); lcd.print("CRC is not valid!"); return -1002; } if ( addr[0] != 0x10 && addr[0] != 0x28) { lcd.setCursor(0, 1); lcd.print("NOT recognizd!"); return -1003; } ds1.reset(); ds1.select(addr); ds1.write(0x44,1); byte present = ds1.reset(); ds1.select(addr); ds1.write(0xBE); for (int i = 0; i < 9; i++) { data[i] = ds1.read(); } ds1.reset_search(); byte MSB = data[1]; byte LSB = data[0]; float TRead = ((MSB<<8) | LSB); float Temperature = TRead / 16; return Temperature; }
P.S извиняюсь за гору текста, хотелось поделиться первым впечатлением, если необходимо впреть буду писать коротко и по делу :)
строки 64, 65 - в сетап
функции стр. 87...122 и стр. 123...158 - можно превратить в одну с параметрами - какой опрашивать и в какую строку выводить
функции стр. 87...122 и стр. 123...158 - можно превратить в одну с параметрами - какой опрашивать и в какую строку выводить
Изначально так и хотел сделать. Но не удалось разобраться как объяснить функии с каким объектом библиотеки onewire ей работать, DS1 или DS2.
На случай если возникнет такой вопрос сразу отвечу: знаю о том что данные датчики имеют свои адреса, знаю что пожно подключить их последовательно на один порт. Сделал это для практики, получилось и разобрал и подключил их к разным пинам, потому что они могут выйти из строя и придется их заменить, посчитал что лучше не привязывать показания к конкретному адресу датчика, дабы не переписывать счетч при замене датчика
строки 64, 65 - в сетап
Перенес, спасибо. Забыл совсем про них
1 - Изначально так и хотел сделать. Но не удалось разобраться как объяснить функии с каким объектом библиотеки onewire ей работать, DS1 или DS2.
2 - ...посчитал что лучше не привязывать показания к конкретному адресу датчика, дабы не переписывать счетч при замене датчика...
наверное , можно в функцию передать и объект DS1, DS2 или номер пина - может кто из "взрослых" подскажет :)
я - точно нет
Как вариант подключения на один пин: в момент запуска сверяем адреса с записанными в EEPROM, если соответствуют - переходим в штатный режим. Если не соответствуют, перезаписываем новые адреса, требуем нагреть один из датчиков, по нагреву записываем дополнительно к адресу признак местонахождения.
Бяка из разряда шизофрении, если зачем то поменяем датчики местами.
Доброго времени суток, не могу разобраться как подключаеться фоторезистор по вашему скетчу, если есть возможность накидайте пожалуйста схему подключения, зранее спасибо!
Один контакт к А0, другой к 5V.
В ходе горы работы которая внезапно на меня навалилась некогда было писать, но так как нужно было духовно обогащаться из отображения температуры плавно перешел на Старт двигателя с кнопки... Могу выложить свежеиспеченный релиз, НО заранее предупреждаю(!) работает он только в условиях "лаборатории" по двум простым причинам:
1. Написаный код слишком "топорный" и как полетный вариант еще не годится
2. Для работы с машиной необходимо провести ряд тестов безопасности, чтобы не еб....(ну вы поняли :) )
Пока что обладает следующими возможностями:
1. Управление только одной кнопкой
2. Возможна передача управления "замку зажигания" и наоборот(в случае если надо выйти, а машину глушить не надо, можно передать управление ардуинке не выключая двигатель, затем вытащить ключ(включив штатную блокировку руля) и выйти по своим делам)
3. Отказ в запуске в случае если АКПП не в положении "P"
4. Отказ в запуске стартера если двигатель на момент нажатия активен
Если кому интересно, подготовлю материал и выложу в отдельной теме. Т.к намечается неминуемое продолждение с нарастающей проблематичностью. Изначальный план развития по пунктам выглядит так:
1. Старт/Стоп двигателя с кнопки
2. Автостарт/стоп двигателя по указаным параметрам
3. Старт/Стоп двигателя и управление параметрами через приложение телефона по Bluetooth
4. [половина знаний уже есть] Старт/Стоп двигателя + контроль показателей + логирование показателей в облако
5. [думаю получится добиться результата] Удаленное управление в радиусе 2-3м от машины (иногда знаете бывают моменты когда нужно подтолкнуть самого себя, или же посмотреть что происходит под колесами но изнутри как известно не видно)
6. [надеюсь доживу и мозгов хватит :) не уверен что на arduino] Следование(при необходимости) за источником сигнала(маячек на водителе) в радиусе 2-3метров, в случае если достаточно места для движения