Изменение значения АЦП после изменения значения Timer1 в программе

Я пишу код, в котором analogRead() считывает значение АЦП из загрузки. После чтения значения ADC, если оно не находится в диапазоне, мне нужно манипулировать значением Timer1. Что также претерпевает изменения d. Но после изменения значения таймера, если значение нагрузки снова восстанавливается, АЦП не показывает снова то же значение, а показывает какое-то другое значение.

Пожалуйста, обратитесь к приведенному ниже коду:

#include <TimerOne.h>

int LED = 13;
int IN0 = 12;
int IN1 = 11;
int OUT1 = 10;
int OUT2 = 9;
int OUT3 = 8;
int OUT4 = 7;
// с плавающей запятой A0;
//инт OUT5 = 6;
const float refvolt = 5.0;
int volts = 0;
byte tempL_flag = 0;
float samples, loadval, avgacs, acsvaluef =0;
float refval = 2.0;
bool lflag=0;
unsigned long count = 0;

void setup()
{
    pinMode(IN0, INPUT);
    pinMode(IN1, INPUT);
    pinMode(OUT1, OUTPUT);
    pinMode(OUT2, OUTPUT);
    pinMode(OUT3, OUTPUT); 
    pinMode(OUT4, OUTPUT);
    pinMode(LED, OUTPUT);
    pinMode(A0, INPUT);
    // цифровая запись (OUT3, LOW);
    Timer1.initialize(370000);
    Serial.begin(9600);
}

word ADC_READ(byte sample, byte tim, byte CH)
{
    word adcdata;
    word avrdata;
    word abcdata;
    byte i;

    for(i=0; i<sample; i++)
    {
        adcdata = 0;
        adcdata = analogRead(CH);
        avrdata = avrdata + adcdata;
        delay(tim);
    }
    return(avrdata/sample);
}

void flash_L()
{
    digitalWrite(LED, !digitalRead(LED));
    digitalWrite(OUT4, !digitalRead(OUT4));

    if (digitalRead(OUT4)==1)
    {
        loadval = ADC_READ(10, 10, A5);
        Serial.println(loadval);

        if(loadval < refval)
        {
            Timer1.initialize(185000);
        }
        else
        {
            tempL_flag = 1;
        }
        return;
    }
}

void loop() {

    delay(2000);

    if(digitalRead(IN0)==1)
    {
        Timer1.attachInterrupt(flash_L);
    }
    else if(digitalRead(IN0)==0)
    {
        digitalWrite(LED, LOW);
        digitalWrite(OUT4, LOW);
    }
}

, 👍1

Обсуждение

сколько раз вы хотите подключить одно и то же прерывание? Он снова начинает считать при подключении. Поместите attachInterrupt в setup(). И я бы не стал читать АЦП в прерывании., @Juraj

Прерывание генерируется только при чтении ввода. Да, в прерывании есть АЦП, я написал функцию для выборки. loadval = ADC_READ(10, 10, A5);, @Hrishikesh Dixit

Я не понимаю, почему IN0 HIGH может иметь только один цикл цикла(). И вы никогда не отключаете прерывание и не устанавливаете его обратно на 370000., @Juraj

Позволь мне объяснить. Если высокий уровень достигает IN0, таймер будет на 370000. Произойдет прерывание таймера. Он будет читать АЦП при нагрузке. Если нагрузка находится в диапазоне 370000, процесс продолжится. Если нет, то 185000. Но после того, как нагрузка выйдет за пределы допустимого диапазона и таймер будет на 185000, если нагрузка восстановится, таймер должен вернуться на 370000. Но даже если нагрузка восстановится, значение АЦП изменится и будет не таким, как в предыдущем случае. Я не могу вернуться к 370000. Надеюсь, теперь понятно., @Hrishikesh Dixit

«Если высокое значение достигает IN0, таймер будет на 370000». как? «Произойдет прерывание таймера» и что будет делать? функция еще не привязана к прерыванию., @Juraj

@Juraj, сэр, если вы ссылаетесь на код, в setup () таймер был инициализирован до 370000. IN0 будет высоким внешним переключателем. Вы можете видеть в цикле (), если IN0 имеет высокий уровень, прерывание подключено, flash_L - это ISR. В ISR светодиод и лампочка переключаются. Если это не отвечает на ваш qstn. Я думаю, что не получаю ваш qstn, @Hrishikesh Dixit

IN0 ВЫСОКИЙ, прерывание прикрепляется. при следующих кратных 370000 микросекундах он срабатывает, а затем всегда снова срабатывает через следующие 370000 или 185000 микросекунд., @Juraj

@Juraj Я думаю, что не могу понять, что ты говоришь. Я не понимаю ваш вопрос. 370000 изменится на 185000 только в том случае, если нагрузка не находится в допустимом диапазоне. Если нагрузка возвращается в диапазон после искажения, я не получаю то же значение АЦП, которое показывалось до искажения., @Hrishikesh Dixit

вы понимаете, что установленное значение таймера TimerOne - это период, в течение которого прикрепленная функция будет вызываться повторно? поэтому вы хотите присоединить прерывание в setup() или отсоединить его в прерывании. вы хотите, чтобы он запускался многократно или как один выстрел?, @Juraj

@Юрай, да, я понимаю. Это означает, что через 370000 микросекунд будет вызван interuupt, и для этого мне нужно написать ISR. Вы можете видеть в setup(), что я инициализировал таймер. в цикле было вызвано прерывание (flash_L). после того, как IN0 высокий. да, я хочу запускать его каждый раз, когда IN0 высокий., @Hrishikesh Dixit

он будет работать всегда после следующего периода после подключения. и он не будет работать 300000 после того, как вы его прикрепите. он будет работать 300000 микросекунд после того, как вы инициализируете период. так что логика вашего скетча не имеет смысла, потому что вы не понимаете как работает библиотека TimerOne, @Juraj

https://www.pjrc.com/teensy/td_libs_TimerOne.html, @Juraj

OP продолжает говорить о том, что он возвращается к 370000, но я не вижу нигде в коде, где это происходит. Как только он будет установлен на 185000, он всегда будет оставаться там, независимо от нагрузки., @Delta_G

@Delta_G да, в коде он нигде не возвращается к 185000 bcz после восстановления нагрузки, значение ADC не возвращается. Поэтому я не писал эту часть кода. Моя основная цель - восстановить значение АЦП, а затем изменить значение таймера., @Hrishikesh Dixit

@Juraj Хорошо, спасибо за помощь. Но правильное выполнение этого таймера даст правильные значения АЦП? Помогите мне в этом, если таймер и АЦП связаны одинаково, @Hrishikesh Dixit

@Juraj Я попробовал ваше предложение и изучил ссылку, которой вы поделились. Затем инициализируется таймер после высокого уровня IN0 и YES!! готово. Большое спасибо. :), @Hrishikesh Dixit


1 ответ


1

ADC снова не показывает то же значение

Вы неправильно читаете ADC, поэтому ADC_READ() может вернуться что-либо. См. комментарии в коде:

word ADC_READ(byte sample, byte tim, byte CH)
{
    word adcdata;  // не нужно
    word avrdata;  // не инициализирован
    word abcdata;  // не используется
    byte i;
    for (i = 0; i < sample; i++)
    {
        adcdata = 0;  // бесполезный
        adcdata = analogRead(CH);
        avrdata = avrdata + adcdata;
        delay(tim);
    }
    return (avrdata/sample);
}

Большая проблема заключается в том, что avrdata не инициализируется. Его начальное значение равно что там осталось (в стеке или каких-то регистрах процессора) по коду что бегало раньше. Затем значение, возвращаемое функцией, трудно прогнозировать и зависит от того, что делает остальная часть программы.

Другие замечания, которые я оставил в комментариях, не так уж проблематичны, хотя они показывают некоторую нехватку внимания к деталям. Такой же для некоторых плохо названных переменных. Вот как бы я это реализовал функция:

word ADC_READ(byte samples, byte time, byte channel)
{
    word sum = 0;
    for (int i = 0; i < samples; i++)
    {
        sum += analogRead(channel);
        delay(time);
    }
    return sum/samples;
}
,

Сэр, я попробую ваше предложение. Спасибо, @Hrishikesh Dixit

это не работает, сэр, я попробовал ваш код. Я думаю, что это проблема с таймером и функцией АЦП, возвращающейся к 370000 с 185000., @Hrishikesh Dixit

@HrishikeshDixit: я не решаю проблему с таймером. Я просто показываю вам, как правильно усреднять показания АЦП, чего программа, которую вы разместили, не делает., @Edgar Bonet

Сэр, спасибо за предложение, оно сохранило переменную и несколько строк кода. Спасибо!, @Hrishikesh Dixit