Вольтметр и ШИМ одновременно

Тема в разделе "Arduino & Shields", создана пользователем Даниил5820, 10 дек 2013.

  1. Помогите пожалуйста с решением задачи!!! Ардуино используется для ШИМ разгона (для начала диода) и одновременно надо им же измерять напряжение на диоде. Но возникают две проблемы: Как одновременно выполнять ШИМ разгон и измерять напряжение? Как сделать чтобы выводилось среднее значение напряжения на диоде(При измерении без ШИМ разгона показывает значения 0 и 4,05-4,08, а необходимо среднее значение как на обычном вольтметре)?
     
  2. Unixon

    Unixon Оракул Модератор

    Код (Text):
    const byte PIN_LED = 13;
    const byte PIN_V_SENSE = A0;
    const byte PIN_V_CTL = A1;

    const int AVERAGE_COUNT = 1000;
    const float V_REF = 5.0;

    int level = 0;
    int count = 0;
    long int sum = 0;

    void setup()
    {
     Serial.begin(9600);
     pinMode(PIN_LED,OUTPUT);
     level = analogRead(PIN_V_CTL);
     analogWrite(PIN_LED, level);
    }

    void loop()
    {
     {
      int new_level = analogRead(PIN_V_CTL);
      if (level != new_level)
      {
      level = new_level;
      analogWrite(PIN_LED, level);
      }
     }
     if (count < AVERAGE_COUNT)
     {
      sum += analogRead(PIN_V_SENSE);
      count++;
     }
     else
     {
      float average = V_REF*((float)sum/(float)AVERAGE_COUNT);
      Serial.print("V_avg = "); Serial.print(average); Serial.println("V");
      sum = 0; count = 0;
     }
    }
     
  3. Unixon

    Unixon Оракул Модератор

    p.s. Что значает "ШИМ разгона (для начала диода)" ? :confused:
     
  4. ШИМ используется для постепенного увеличения яркости диода.
     
  5. а можно пояснение к программе?
     
  6. Megakoteyka

    Megakoteyka Оракул Модератор

    Диод и светодиод - разные вещи.
     
  7. fr0ster

    fr0ster Гик

    Для ШИМ настройте таймер, для замера напряжения настройте АЦП и прерывание завершения АЦП конвертации.
    Для примера код для ардутины, где ШИМ от таймера настроен и отлавливается прерывание аналогового компаратора, вам вместо него нужно запилить прерывание АЦП
    Код (Text):

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/sleep.h>
    #include <util/delay.h>

    const int delay_tome = 1000;
    const int max_lumen = 255;
    const int min_lumen = 1;

    int pwm_pb2;
    int pwm_pb3;
    int pwm_pd5;

    enum {
       DOWN, UP
    };

    int ch_red() {
       static int direct;
       static int value = 1;
       if (value >= max_lumen) {
         direct = DOWN;
       } else if (value <= min_lumen) {
         direct = UP;
       };
       if (direct == UP) {
         value *= 2;
       } else {
         if (value >= min_lumen)
           value /= 2;
         else
           value = min_lumen;
       };
       if (value >= max_lumen)
         value = max_lumen;
       if (value <= min_lumen)
         value = min_lumen;
       return value;
    }

    int ch_green() {
       static int direct;
       static int value = 1;
       if (value >= max_lumen) {
         direct = DOWN;
       } else if (value <= min_lumen) {
         direct = UP;
       };
       if (direct == UP) {
         value *= 2;
       } else {
         value /= 2;
       };
       if (value >= max_lumen)
         value = max_lumen;
       if (value <= min_lumen)
         value = min_lumen;
       return value;
    }

    int ch_blue() {
       static int direct;
       static int value = 1;
       if (value >= max_lumen) {
         direct = DOWN;
       } else if (value <= min_lumen) {
         direct = UP;
       };
       if (direct == UP) {
         value *= 2;
       } else {
         value /= 2;
       };
       if (value >= max_lumen)
         value = max_lumen;
       if (value <= min_lumen)
         value = min_lumen;
       return value;
    }

    void loop_step() {
       static int st = 0;
       if (st <= 6)
         st++;
       pwm_pb2 = ch_red();
       if (st >= 3)
         pwm_pb3 = ch_green();
       if (st >= 6)
         pwm_pd5 = ch_blue();
       //пауза
       _delay_ms(delay_tome);
    }

    void ioinit(void) {
       ADCSRB &= ~(_BV(ACME));
       ACSR |= _BV(ACIE); // | _BV(ACBG);
       ACSR &= ~(_BV(ACIS0) | _BV(ACIS1) | _BV(ACD));

    //   DDRB = 0x00;
    //   PORTB = 0x00;
       //PB3 и PB4 на выход
       DDRB |= _BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3);
       //PD5 на выход
       DDRD |= _BV(PD5);
       //ножки PD6,PD7 высокоомный вход(без внутренних подтягивающих сопротивлений)
       PORTD &= ~(_BV(PD6)) & ~(_BV(PD7));

       //TCNT0 = 255;
       OCR0A = 0;
       OCR0B = 0;

       //TCNT1 = 0;
       OCR1A = 0;
       OCR1B = 0;

       //TCNT2 = 0;
       OCR2A = 0;
       OCR2B = 0;

       /* Timer 0 is 8-bit PWM. */
       TCCR0A = _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
       TCCR0B |= _BV(CS02) | _BV(WGM02);
       /* Timer 1 is 8-bit PWM. */
       TCCR1A = _BV(COM1B1) | _BV(WGM11) | _BV(WGM10);
       TCCR1B |= _BV(CS12) | _BV(WGM12);
       /* Timer 2 is 8-bit PWM. */
       TCCR2A = _BV(COM2A1) | _BV(WGM21) | _BV(WGM20);
       TCCR2B |= _BV(CS22) | _BV(WGM22);
    //   GTCCR

       TIMSK0 |= _BV(TOIE0);// | _BV(OCIE0B);
       TIMSK1 |= _BV(TOIE1);// | _BV(OCIE1B);
       TIMSK2 |= _BV(TOIE2);// | _BV(OCIE2A);

       sei ();
    }

    void chech_aco() {
       if (ACSR & _BV(ACO)) {
         PORTB &= ~(_BV(PB0));
         PORTB |= _BV(PB1);
       } else {
         PORTB |= _BV(PB0);
         PORTB &= ~(_BV(PB1));
       }
    }

    int main(void) {

       ioinit();
       chech_aco();
       /* loop forever, the interrupts are doing the rest */
       for (;;)
         loop_step();
       //sleep_mode();
       return (0);
    }

       ISR(ANALOG_COMP_vect)
    {
       chech_aco();
    }

       ISR(TIMER0_OVF_vect)
    {
       OCR0A = pwm_pd5;
    }

       ISR(TIMER1_OVF_vect)
    {
       OCR1B = pwm_pb2;
    }

       ISR(TIMER2_OVF_vect)
    {
       OCR2A = pwm_pb3;
    }