Ошибка на выходе PWM при использовании ATmega328P-au и Atmel Studio

#c #adc #pwm #atmelstudio #arduino-nano

#c #АЦП #pwm #atmelstudio #arduino-nano

Вопрос:

Привет всем, 

Я новичок в программировании AVR, и меня попросили разработать плату, которая могла бы считывать значения аналогового датчика и устанавливать выход PWM. В конструкцию был включен потенциометр, который выполнял роль процентного диммера между двумя сигналами PWM. 

Поскольку мой опыт программирования только в среде IDE Arduino, при переходе на Atmel Studio 7 я использовал опцию импорта кода Arduino и продолжил программирование ISP с использованием Atmel ICE. 

Сама модель состоит из двух аналоговых сигналов (датчика и потенциометра) и 4 шим-выходов (две пары сигналов). Более того, код основан на базовом конечном автомате:
1) Считайте датчик и потенциометр, которые определяют выходное значение PWM. 
2) Случай 1: увеличение выходного значения PWM
3) Случай 2: уменьшение выходного значения PWM
4) Случай 3: сохранение выходного значения PWM

Однако всякий раз, когда я помещаю датчик под свою лампу (управляемую PWM), он начинает мерцать, и я не могу достичь "стабильного состояния". Моим возможным решением было бы считывать значение датчика и иметь среднее значение между самым высоким и более низким значением, которое позже будет использоваться для установки уровня выходного сигнала PWM, а второй будет использовать прерывания, но я не знаю, как их реализовать. 

Примечание: частота установлена на 10 МГц, потому что я использую 3,3 В, поэтому cristal был выбран в соответствии с входным значением
 /*Begining of Auto generated code by Atmel studio */
#define F_CPU 10000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <Arduino.h>

/*End of auto generated code by Atmel studio */

//Pinout
const int C1 = 9;                     // Select the pin for Channel 1 PWM Dimming (Sunrise)
const int C2 = 6;                      // Select the pin for Channel 2 PWM Dimming (Daylight)
const int C3 = 5;                      // Select the pin for Channel 3 PWM Dimming (Sunrise 2)
const int C4 = 3;                      // Select the pin for Channel 4 PWM Dimming (Daylight 2)
const int CM = A1;                     // Select the pin for the color mixer (Potentiometer)
const int ALS = A0;                    // Select the pin for the ALS signal

//Variables
int ch = 0; // Current PWM level
int count = 0;
float ch1 = 0; // Color mixer factor of the Channel 1 and 3 PWM (0% - 100%)
float ch2 = 0; // Color mixer factor of the Channel 2 and 4 PWM (0% - 100%)
int mixer = 0; // Potentiometer value
int pwm = 0;   // PWM counter 
int th = 200;  // Threshold value (light sensitivity)
int als = 0;   // Stores the value of the ALS
int mst = 0;   // Maschine state
int sum = 0;   // Average ALS value
int sum2 = 0;  // Average trimmer value
int wait = 100; // Delay value
int f = 0; //1 Machine State counter
int i = 0; //2 Machine State counter

//Setup
void setup() {
//  I/O Pins
pinMode(C1, OUTPUT);
pinMode(C2, OUTPUT);
pinMode(C3, OUTPUT);
pinMode(C4, OUTPUT);
pinMode(ALS, INPUT);
pinMode(CM, INPUT);

//  Set PWM outputs to LOW
analogWrite(C1, ch1);
analogWrite(C2, ch2);
analogWrite(C3, ch1);
analogWrite(C4, ch2);
//Serial.begin(9600);
}

void loop() {

//State machine init
switch(mst){
    case 0:
    // Read the value from the Ambient Light Sensor and the Mixer Pin
    for(int i =0; i<wait; i  ){
        delay(0.00001);
        als = analogRead(ALS);
        sum = als   sum;
    }
    
    // Obtain an average ALS value
    sum = sum/wait;
    mixer = analogRead(CM);
    
    //Serial.println(sum2);
    if(sum > th) {
        sum = th;
    }
    if(mixer >= 1000) {
        mixer = 1000;
    } else {

    }
    // Re-map average value to PWM level (0-255 == 0-100%)
    pwm = map(sum, 0, th, 255, 0);
    
    
    //Declare the color mixer percentage 
    if((mixer>=0)amp;amp;(mixer<512)){
        ch1 = 100;
        ch2 = (100*mixer)/512;
        } else if(mixer<1022) {
        ch1 = map(mixer, 512, 1000, 100, 0);
        ch2 = 100;
        } else {
        ch1 = 0;
        ch2 = 100;
        }
        
    //Serial.print(mixer);
    ch1 = ch1/100;
    ch2 = ch2/100;
    
    //Increase PWM
    if(ch<pwm-5){
    mst = 1;
    }
    
    //Change to the second stage
    if(ch>pwm 5){
        mst = 2;
    }
    
    //Change to third stage
    if((ch > pwm-5) amp;amp; (ch < pwm 5)){
        mst = 3;
    }
    delay(0.000001);
    break;

    case 1: //Current PWM level less than the actual ALS value
        //Compare PWM and ch1 to make a gradual change
        count = ch 3;
        if (count > 255)
        {
            count = 255;
        }
        ch = count;
        analogWrite(C1, (ch*ch1));
        analogWrite(C2, (ch*ch2));
        analogWrite(C3, (ch*ch1));
        analogWrite(C4, (ch*ch2));
        delay(0.0000001);
        //Return to initial state
        mst = 0;
    break;

    case 2: //Current PWM level greater than the actual ALS value
        //Compare PWM and ch1 to make a gradual change
        count = ch-3;
        if (count < 0)
        {
            count = 0;
        }
        ch = count;
        analogWrite(C1, (ch*ch1));
        analogWrite(C2, (ch*ch2));
        analogWrite(C3, (ch*ch1));
        analogWrite(C4, (ch*ch2));
        delay(0.0000001);
        //Return to initial state
        mst = 0;
    break;

    case 3: //Current PWM level equal than the actual ALS value
        //Keep tha output value
        analogWrite(C1, (ch*ch1));
        analogWrite(C2, (ch*ch2));
        analogWrite(C3, (ch*ch1));
        analogWrite(C4, (ch*ch2));
        //Return to initial state (Read ALS amp; Trimmer)
        mst = 0;
        delay(0.0000001);
    break;

    default:
    //Empty
    break;
}
}
  

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

1. Почему вы читаете ALS много раз, суммируя результат только для записи значения суммы (с прямым чтением ALS), не используя его? Вы хотели вместо этого разделить сумму на ожидание, чтобы получить среднее значение?

2. Привет, Натан, спасибо за ваш комментарий, в коде была ошибка, когда я пытался отследить текущее значение датчика. Тем не менее, ошибка относится к этому исправленному коду.

3. Еще одна вещь, которую я отметил, это то, что ваша карта sum to PWM изменяет диапазон, поэтому sum = 0 -> pwm = 255 и sum = th -> pwm = 0. Это может быть преднамеренным, поэтому игнорируйте, если это так.

4. Я только что перечитал ваш вопрос, и похоже, что вы управляете лампой с помощью PWM, используя датчик для обнаружения света, а затем изменяя PWM. Этой системой будет очень сложно управлять, потому что у вас есть петля обратной связи. Основываясь на вашем описании того, что происходит, я бы сказал, что у вас колеблющийся контур отрицательной обратной связи. Какой результат вы хотите получить от этого устройства? Можете ли вы более подробно рассказать о том, чего вы хотите достичь?

5. Да, точно. Лампа будет автоматически управляться в соответствии с сигналом датчика. Этот датчик генерирует фототок, и я беру значение последовательно подключенного резистора; ток увеличивается при увеличении освещенности. Но поскольку лампа не предназначена для включения при достаточном освещении помещения, поэтому применяется цикл отрицательной обратной связи. Пока датчик не помещен под лампу, он, кажется, работает нормально. Но если компонент обнаруживает какое-либо отражение света от стены, он начинает мерцать.