Замер напряжения ардуинкой.

Тема в разделе "Схемотехника, компоненты, модули", создана пользователем pixel28, 31 июл 2017.

  1. pixel28

    pixel28 Нуб

    Всем привет. Имею скетч (не мой). Есть часть кода, которая измеряет напряжение на ардуинке.
    Код (C++):
    // return current VCC voltage in mV
    unsigned long readVCC() {
      unsigned long result;
      // Read 1.1V reference against AVcc
      ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
      delay(2); // Wait for Vref to settle
      ADCSRA |= _BV(ADSC); // Convert
      while (bit_is_set(ADCSRA, ADSC));
      result = ADCL;
      result |= ADCH << 8;
      result = 1126400L / result; // Back-calculate AVcc in mV
      return result;
    }
    Хочу сделать так, что-бы напряжение замерялось на аналоговом пине A4.
    На данный момент сделал так:
    Использовал опорное 1.1в.

    Код (C++):
    // return current VCC voltage in mV
    unsigned long readVCC() {
      unsigned long result;
      int val = analogRead(A4);
      result = (val / 1023 ) * 1100;
      return result;
    При подключении li-ion акб показало 1.1 вольт. Понял, что максимальное измеряемое напряжение будет 1.1в, что меня не устроило и решил сделать опорное 5 вольт. Делитель городить не захотел ибо он внесет свои погрешности. А вот 5 вольт у меня стабилизированы хорошо ( до сотых ) и измерять можно будет до 5 вольт. Код изменил, поменял множитель, прописал вместо
    Код (C++):
    analogReference(INTERNAL);
    Код (C++):
    analogReference(DEFAULT);
    Теперь напряжение не замеряет и показывает 0 вольт.
    На всякий случай прикладываю полный код.
     

    Вложения:

    • Код.txt
      Размер файла:
      39,5 КБ
      Просмотров:
      14
  2. mcureenab

    mcureenab Гуру

    Вместо
    (val / 1023 ) * 1100
    используйте функцию map.
     
  3. pixel28

    pixel28 Нуб

    Спасибо большое, все заработало, даже не знал о существовании данной функции.
    Код (C++):
    // return current VCC voltage in mV
    unsigned long readVCC() {
      unsigned long result;
      int val = analogRead(A4);
      result = map(val, 0, 1023, 0, 5000);
      return result;
      Serial.print(result);
    Теперь буду её использовать.
    А почему тогда (val / 1023 ) * 1100 не работало должным образом? Очень интересно. На другом проекте все отлично работало.
     
  4. mcureenab

    mcureenab Гуру

    Целочисленное деление
    val / 1023
    округляется до целого отбросом дробной части.
    В "другом проекте" может быть тип val был не целым или порядок операторов был другой.
     
  5. BAR__MEN

    BAR__MEN Гуру

    :confused:
     
  6. AndroT

    AndroT Guest

    Можно пояснить каждую строчку?
    Очень интересно как это работает.
     
  7. BAR__MEN

    BAR__MEN Гуру

    Вы о коде ошибки;)?
     
  8. AndroT

    AndroT Guest

    :) :)
     
  9. Unixon

    Unixon Оракул

    Функция map() тоже целочисленная, точность не особо хорошая.
    Лучше так:
    Код (C++):
    long fmap(long x, long in_min, long in_max, long out_min, long out_max)
    {
      return floor(0.5 + (float)((x - in_min) * (out_max - out_min)) / (float)(in_max - in_min) + out_min);
    }
     
    Последнее редактирование: 9 авг 2017
    ИгорьК нравится это.
  10. b707

    b707 Гик

    Хм... зачем так сложно-то? в итоге в скобках перемудрили, у вас "+ out_min" попал в знаменатель дроби, а ему там не место. Кроме того, действительные числа нам нужны только в операции деления, целочисленные сложение и умножение ошибок не дают, поэтому достаточно привести к действительному типу один из перандов - либо числитель, либо знаменатель.
    Код (C++):
    long fmap(long x, long in_min, long in_max, long out_min, long out_max)
    {
      return floor(0.5 + out_min + (float)((x - in_min) * (out_max - out_min)) / (in_max - in_min) );
    }
    а вообще, в изначальном коде достаточно было добавить два символа, чтобы все заработало:
    (val / 1023.0 ) * 1100
     
    Последнее редактирование: 9 авг 2017
  11. Unixon

    Unixon Оракул

    Это не я перемудрил, вот оригинальная функция map из IDE 1.6.5 :
    Код (C++):
    long map(long x, long in_min, long in_max, long out_min, long out_max)
    {
      return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    }
     
     
  12. Unixon

    Unixon Оракул

    И это будет лучше, чем целочисленный map(). Только памяти съест много и скорости под плавающую точку.
     
  13. b707

    b707 Гик

    А вы сравните свой код и этот :)
     
  14. Unixon

    Unixon Оракул

    Блин, скобки не там поставил :)