Датчик света. Замеры
- Войдите на сайт для отправки комментариев
Ср, 07/12/2016 - 15:01
Понадобилось посмотреть значения света на улице в разное время суток. Если вдруг кому пригодится.
Записывает значения света в EEPROM в течении суток через 15мин. Время берется с GPS приемника по Rx.
#include <EEPROM.h> #include <SoftwareSerial.h> #include <TinyGPS.h> TinyGPS gps; SoftwareSerial ss(2, 3); // К D2 подключается Tx GPS приемника int timeoffset = 3; // Часовой пояс int pinAn = 2; // К A2 подключается вход с фоторезистора unsigned long pauseL = 0; int arrayL[5] = {0, 0, 0, 0, 0}; byte s = 0; int currentL = 0; boolean l = false; int addr = 0; void EEPROMWriteInt(int p_address, int p_value) // Запись в EEPROM значений типа int { byte lowByte = ((p_value >> 0) & 0xFF); byte highByte = ((p_value >> 8) & 0xFF); EEPROM.update(p_address, lowByte); EEPROM.update(p_address + 1, highByte); } void setup() { Serial.begin(9600); ss.begin(9600); //pinMode(pinAn, INPUT); Serial.print("Simple TinyGPS library v. "); Serial.println(TinyGPS::library_version()); Serial.println("by Mikal Hart"); Serial.println(); } void loop() { bool newData = false; unsigned long chars; unsigned short sentences, failed; // For one second we parse GPS data and report some key values for (unsigned long start = millis(); millis() - start < 1000;) { while (ss.available()) { char c = ss.read(); // Serial.write(c); // uncomment this line if you want to see the GPS data flowing if (gps.encode(c)) // Did a new valid sentence come in? newData = true; } } if (newData) { int year; byte month, day, hour, minute, second, hundredths; gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths); hour = hour + timeoffset; Serial.print(hour); Serial.print(":"); Serial.print(minute); Serial.print(":"); Serial.println(second); if (l && (minute == 0 || minute == 15 || minute == 30 || minute == 45)) { addr = hour*8+(minute/15)*2; // Высчитывается адрес ячейки EEPROM в зависимости от времени EEPROMWriteInt(addr, currentL); Serial.print("Eeprom write "); Serial.print(addr); Serial.print(" "); Serial.println(currentL); } } //Здесь значения со света считываюся 5 раз через 1 сек и высчитывается среднее, если значения отличается более чем на 10 то изменить значение переменной currentL if (pauseL == 0) {pauseL = millis();} else { if ((millis()-pauseL) > 1000) //Если прошло более 1сек между опросами { if (s < 5) { arrayL[s] = analogRead(pinAn); s++; } else // Если выполнено 5 опросов { // Ищем максимальное значение int maxL = arrayL[0]; int imaxL = 0; for (int x = 1; x < 5; x++) { if (maxL < arrayL[x]) { maxL = arrayL[x]; imaxL = x; } } //Ищем минимальное значение int minL = arrayL[0]; int iminL = 0; for (int x = 1; x < 5; x++) { if (minL > arrayL[x]) { minL = arrayL[x]; iminL = x; } } // Вычисляем среднее значение отбрасывая макс и мин int sr = 0; for (int x = 0; x < 5; x++) {if (!(imaxL == x) && !(iminL == x)) {sr = sr + arrayL[x];}} // Если все значения одинаковы, то imaxP = iminP и делить надо на четыре int temp1 = 0; int st = 0; if (imaxL == iminL) {temp1 = sr / 4;} else {temp1 = sr / 3;} st = currentL - temp1; st = abs(st); if (st > 10) {currentL = temp1;} s = 0; l = true; } pauseL = 0; } } }
Дальнейшее чтение EEPROM
#include <EEPROM.h> unsigned int value = 0; int hour[24] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}; int minute[4] = {0, 15, 30, 45}; int addr = 0; unsigned int EEPROMReadInt(int p_address) { byte lowByte = EEPROM.read(p_address); byte highByte = EEPROM.read(p_address + 1); return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00); } void setup() { Serial.begin(9600); pinMode(13, OUTPUT); Serial.println("EEPROM read..."); for (int i = 0; i < 24; i++) { for (int m = 0; m < 4; m++) { addr = hour[i]*8 + (minute[m]/15)*2; value = EEPROMReadInt(addr); Serial.print(hour[i]); Serial.print(":"); Serial.print(minute[m]); Serial.print(" = "); Serial.println(value); } } } void loop() { digitalWrite(13, HIGH); delay(300); digitalWrite(13, LOW); delay(300); }
Тоже выложу пример измерения освещенности в больших пределах без использования АЦП. Проверено на ESP8266.
Суть в измерении времени RC цепи. Схема как у вас, только вместо резистора конденсатор на 2,2 мкФ. Фоторезистор к +, конденсатор к минусу, их соединение к пину, имеющему прерывания. Перед замером разряжаем конденсатор пином в 0, потом отсчитываем время до прерывания. Время зарядки конденсатора и берем как попугаи освещенности. Значение времени получаются от 15 мкс при ярком свете до 5000000 мкс при почти полной темноте. Эти попугаи можно приводить к каким либо единицам. Пробовал брать кубический корень из полученной цифры, тогда логарифмичность шкалы уменьшается и более приятно глазу.
Можно таким образом измерять сопротивление или емкость конденсаторов. Из опастностей: разряд конденсатора идет через пин, т.е. установка большой емкости недопустима!