Вольтлоггер восьмиканальный

17 октября 2016 г. Просмотров: 6683 RSS 1
Самопал

Давно я не брал в руки метлу, но тут пришлось, т.к. братья китайцы ничего не смогли мне предложить.

Задача - наблюдать на графике заряды и разряды последовательно подключенных аккумуляторов в автономных системах, уровень напряжения солнечных панелей и ветрогенераторов да все это в течение длительного времени - сутки-двое-трое...

В общем пришлось создать простенький вольтлоггер, а по русски восьмиканальный напряжометр с записью на СДху.

Основа Ардуино нано, все остальное из подножного хлама.

Кликабельно (если кому-то порвет монитор - это ваши проблемы, зато все видно)

Схема простейшая, лень даже рисовать. Вот вам подключение SD карты без шилдов. Ради разъема раздербанил картридер из фикспрайса.

К ардуине цепляем делители (по принципу как для SDхи) для чтения напряжения через АЦП к ногам А0-А7. Без делителей напряжения мерять можно только до 5 Вольт, для моих задач мало.

Делители считаем на 5В, что бы максимальное напряжение на входе давало 5В на выходе. И сопротивление реальных резисторов заносим в скетч в специальный массив.

Например: А0 подключен напрямую к плюсу АКБ без делителя, ведь там напряжение не превысит 4,3В

На А1 у меня напряжение для замера не должно превышать 16В (один сильно перезаряженный АКБ). Соответственнов на делитель идут резисторы на 4,3кб и 2,0кб. Реально же получились 4300 Ом и 1984 Ома - эти данные в соответствующую позицию массива и заносим.

А2 - 32В (15к и 2,7к) - два АКБ последовательно

А3 - 48В (23к и 2,7к) - три АКБ последовательно

А4 - 64В (18к и 1,5к) - четрые АКБ последовательно

а дальше мне не нужно, но до А7 - можно использовать по тому же принципу. Если на порту подключен делитель и замер не производится - в логах будет ноль. Если нога ардуины без делителя и не подтянута к земле - в логах сыпется замер наводок, порядка 1,5В - на графиках ниже это видно. Это нормально.

Упаковал все в маленький корпус от какой-то китайчатины. Аккумулятор для питания ардуины взял что попался на 1500 мАч, от какого-то сотового. Так же использовал мелкую платку DC-DC на 5В на выходе, забыл отметить на фото, приклеена к АКБ сверху, красная плата под основными делителями. Никакие шилды не использовал.

Вкорячивал все ногами - по супер плотному монтажу видно, но все влезло и работает. Светодиод состояния взял двухцветный с общим катодом от сидюка, токоограничители по 330 Ом подключены на D2 и D3. Горит зеленый и гаснет раз в 15 секунд - все нормально, запись прошла, горит красный - жопа!. Файл на флешке открывается на запись и сразу закрывается. Флеха проживет не долго, лет 150, но зато выдергивать ее можно чуть ли не влюбой момент - все сохранится.

Все измеренные данные льются так же и в последовательный порт, можно подключить комп и посмотреть.

Скрин с выводимыми данным в порт, можно заморочиться с экраном, но мне это лишнее.

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

Скетч Вольтлоггера v4
/****************************************************************************
* Восьмиканальный вольтлоггер для последовательно соединенных
* аккумуляторных или солнечных батарей с записью данных на SD карту
*
* http://www.roft.ru
* http://www.kavelsib.ru
*
****************************************************************************/
#include //Библиотека работы с SD картой
const int chipSelect = 10; //нога чтения данных из SD карты
// резисторы делителей напряжения по портам А0-А7, измерь как можно точнее и занеси в массив
//от их точности зависит точность измерений
const float r1[8] = {0, 4300, 15115, 23410, 18210, 0, 0, 0}; // Омы к вх. напряжению по портам А0-А7
const float r2[8] = {99999999999, 1984, 2691, 2676, 1495, 99999999999, 99999999999, 99999999999}; // Омы подтяжки к земле по портам А0-А7
//нули и девятки там, где делитель не нужен и идет прямой замер,
//например напряжения питания или напряжение батарейки
// эту константу (typVbg) необходимо откалибровать индивидуально, у каждой платы свой внутренний опорник
//используй качественный вольтметр и подстрой показания по напряжению питания
const float typVbg = 1.068; // по докам между 1.0 -- 1.2
float Vcc = 0.0;
float MaxVoltage = 0.0;
#define COUNT 20 //сколько замеров АЦП, чем больше - тем точнее, но дольше каждый замер напряжений
float curVoltage;
String Filename = "log"; //перфикс файла
String dataString = ""; //создание строки для сбора данных в лог
void setup() {
pinMode(2, OUTPUT); //Светодиод ошибки
pinMode(3, OUTPUT); //Светодиод норм

// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("--- Setup ");
Serial.print("
");
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println(" FAILED!!!! ");
digitalWrite(2, HIGH); //Если карта не инициализировалась - зажигаем светодиод ошибки и
digitalWrite(3, LOW); //гасим светодиод норм
// don't do anything more:
return;
}
Serial.println(" OK");
digitalWrite(2, LOW); //Если карта инициализировалась - гасим светодиод ошибки и
digitalWrite(3, HIGH); //зажигаем светодиод норм
// Определяем имя файла в который будем писАть

int Addname=1;
while (SD.exists(Filename + Addname+ ".csv"))//ищем имя файла, которого нет на карте
{
Serial.print ("file ");
Serial.print (Filename + Addname+ ".csv");
Serial.print (" exist");
Serial.print("
");
Addname=Addname+1;
}
Filename=Filename+Addname+".csv"; //собираем имя файла
Serial.print ("log file: ");// объявляем куда будем писать в этот раз
Serial.print (Filename);
Serial.print("
");
delay(1000); //ожидание секунды перед замером
// определение опорного напряжения
analogReference(DEFAULT); // DEFAULT INTERNAL использовать Vcc как AREF
delay(100);
Vcc = readVcc();
MaxVoltage = Vcc / (r2[1] / (r1[1] + r2[1])); //определяем макс напр при замере с учетом резисторов делителя
//analogWrite(A_PIN, 0);
Serial.print("Vcc = ");
Serial.println(Vcc, 4);
Serial.print("Max Vm = ");
Serial.print( MaxVoltage, 4 );
Serial.print("
");
Serial.print("---------------");
Serial.print("
");
delay(200);
dataString += "T,s;Vcc;Vbat;A1;A2;A3;A4;A5;A6;A7
";
}

void loop() {

unsigned long stime=millis()/1000; //замер времени

dataString += stime;
dataString += ";";
dataString += Vcc;
dataString += ";";

// читаем 8 портов и пишем в строку
for (int analogPin = 0; analogPin < 8; analogPin++) {

Vcc = readVcc();
// считываем точное значение АЦП с A0-A7, где находятся делители напряжения
curVoltage = 0.0;
for (int i = 0; i < COUNT; i++) {
curVoltage = curVoltage + analogRead(analogPin);
delay(10);
}
curVoltage = curVoltage / COUNT;
float v = (curVoltage * Vcc) / 1024.0;
float v2 = v / (r2[analogPin] / (r1[analogPin] + r2[analogPin]));


Serial.print(stime);
Serial.print(" Vm");
Serial.print(analogPin);
Serial.print("= ");
Serial.print(v2, 4);
Serial.print("/ Vcc=");
Serial.print(Vcc, 4);
Serial.print("
");
delay(100);

dataString += v2;
if (analogPin < 7) {
dataString += ";";
}
}
// открываем файл
File dataFile = SD.open(Filename, FILE_WRITE);
// если файл доступен - пишем туда:
if (dataFile) {
digitalWrite(3, LOW); //погасили светодиод норм
dataFile.println(dataString);
dataFile.close();
// print to the serial port too:
Serial.print(dataString);
Serial.print("
");
delay(1000);
digitalWrite(3, HIGH); //зажгли светодиод норм

dataString = ""; //очистили строку
}
// если файл не открывается - пишем егогг и зажигаем ошибку
else {
Serial.print("ERROR opening file !!!
");
digitalWrite(2, HIGH); //Если файл недоступен - зажигаем светодиод ошибки и
digitalWrite(3, LOW); //гасим светодиод норм
}
delay(10000); //вкупе примерно 15 сек между измерениями
}
/****************************************************************************
* Функции
****************************************************************************/
float readVcc() {
byte i;
float result = 0.0;
float tmp = 0.0;
for (i = 0; i < COUNT; i++) {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#else
// works on an Arduino 168 or 328
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
delay(3); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
tmp = (high<<8) | low;
tmp = (typVbg * 1023.0) / tmp;
result = result + tmp;
delay(5);
}
result = result / COUNT;
return result;
}

Пояснения по коду: замер ведется в несколько этапов. Сначала меряем 20 раз напряжение питания относительно внутреннего источника напряжения ардуины 1,1В и берем среднее.

Потом относительно измеренного напряжения питания меряем по 20 раз и усредняем напряжение на портах А0-А7. Точность до 4го знака после запятой не обещаю, но у меня 2й знак стабильно совпадает с приличным мультиметром, т.ч. для бытового применения пойдет. Точность зависит от резисторов делителя - берите классом повыше, но если нет - пойдут любые, главное измерьте их сопротивление поточнее и занесите в массив, можно вычислить их и программно, если нет точного прибора, но придется долго перебирать значения.

И выставьте в скетче точно напряжение внутреннего референсного источника ардуины - его нельзя измерить, только подобрать опытным путем. По даташиту лежит в пределах от 1,0 до 1,2 В, у меня 1,068В. Меняем это напряжение до тех пор, пока показания ардуины и показания вашего суперточного напряжометра (вольтметра или мультиметра) не сойдутся. Измеряем напряжение питания 5В и на нем подбираем референсное последовательным приближением.

Если надо подстроить измеренное напряжение по портам А0-А7 - меняйте данные о сопротивлении делителей, в пределах 10-50 Ом у меня все устаканилось.

А теперь самое интересное - графики! то ради чего все затевалось.

Данные пишутся в формате CSV, в качестве разделителя - точка с запятой. Ёксель или опен офис прекрасно понимает. Перед построением графика нужно заменить все точки на зяпятые для жителей постсоветского пространства (десятичный разделитель в соответствии с локализацией своего компа)

Первый график - напряжение аккумулятора в автомобиле от включения зажигания и до выключения зажигания. Видна работа бортового оборудования, работа генератора, включение жопогреек и пр.

Колонки по порядку: T's - время в секундах от момента включения ардуины

Vcc - напряжение питания, чтоб знать, что все хорошо

Vbat, оно же А0, оно же Vm0 - напряжение внутреннего АКБ

А1-А7 замеряемые напряжения по портам.

Второй график - работа умной зарядки на AGM аккумуляторе - постепенный подъем напряжения вкупе с редкими контролями при отключенном заряде.

Внизу видно напряжение питания ардуины и напряжение встроенного АКБ. АКБ к концу замера упал до 2,9В, что здоровья ему не прибавляет. Но т.к. мне данные важнее, то DC-DC будет его сосать до 0,9В - это убъет АКБ, но я буду получать информацию до последнего.

Тот график ради которого эта железка и создавалась. Количество энергии выработанное солнечной батареей за день. В данном случае на графике 31 октября 2016г, день был пасмурный с редкими просветами солнца, после обеда небо совсем заволокло и пошел дождь.

Данным логгером можно снимать такие графики с 8 шт солнечных батарей одновременно и потом сравнивать выработку находя слабые места или бракованные панели. Заряда встроенного аккумулятора хватило на сутки непрерывного замера и судя по напряжению Vbat еще осталась половина.

Обратите внимание - у всех портов для замера будет общий минус. Соответственно 8 каналов - это зависимые каналы. Т.е. для наблюдения последовательно соединенными аккумуляторами пойдет, а для отдельно стоящими - нет, только по одному, если нет возможности их объединить минусами.

Есть вопросы - пишите. Можно в личку.

twitter.com vkontakte.ru odnoklassniki.ru blogger.com liveinternet.ru livejournal.ru
Комментариев: 1
    

    Комментариев: 1

    • Круто, а что с замерами по току? Давно хотел себе наа солнечные батареи поставить логгер выработки. Кстати, покупал у вас в магазине, Электромаг - праильно я понимаю, это же в нем работаете? Прошлым летом покупал у вас панели и все работает. Спасибо.

    Оставьте комментарий!

    grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

    Используйте нормальные имена

    Вы можете войти под своим логином или зарегистрироваться на сайте.

    (обязательно)