ШИМ контроллер на ардуино.

144
144 аватар
Offline
Зарегистрирован: 14.02.2016

Всем привет!

Я не особо сильный ардуинщик,могу только лампочками управлять или типа того. Но потребовалось сделать шим для IGBT модуля на три фазы. Суть такая из постоянного тока получаем переменный три фазы,и изменяя частоту регулируем скорость. В модуле есть 6 транзисторов,которые должны открываться в заданой последовательности. Эта последовательность,жуткая тайна,узнать которую мне не удалось. Зато нашел готовый скетч в интернете,но он не загружается,потому что там переменные не задекларированы.Пишет : exit status 1

'io_init' was not declared in this scope

Помогите исправить,если есть возможность:

#define UN        (400.0)    //napiecie znamionowe silnika
#define FN        (50.0)     //czestotliwosc znamionowa silnika
#define P         (UN/FN)    //wsp. okreslajacy proporcje napiecia do czestotliwoci znamionowej
#define T_PWM     (0.000255) //okres sygnalu PWM - ustawiony przez preskaler w licznikach
#define T_MAX     (4.0)      //okreslenie maksymalnego okresu napiecia wyjsciowego
#define T_MIN     (0.02)     //minimalny okres napiecia wyjsciowego
#define K_MAX     floor(T_MAX/T_PWM)  //liczba wartosci okresu dla T_MAX
#define K_MIN     ceil(T_MIN/T_PWM)   //liczba wartosci okresu dla T_MIN

volatile static unsigned int dlugosc_tab_sin;   //zmienna zawierajaca liczbe wartosci w pelnym
                                                //okresie napiecia wyjsciowego
static unsigned int i = 0;                      //zmienna pomocniacza
volatile static unsigned int licznik_glowny = 0;//zmienna wystepujaca w przerwaniu czyklicznie
                                                //^ co okres T_PWM zwiekszajaca swoja wartosc o 1
static unsigned int next_value_sin = 0; //zmienna ktora wartosc sin nalezy obliczyc
static double t_param=100;              //parametr okreslajacy okres napiecia wyjsciowego
static float t = T_PWM;                 //T_PWM
static float omega_t;                   //pulsacja napiecia wyjsciowego pomnozona przez T_PWM
static float t_out;                     //okres wyjsciowy napiecia
static float U_o_param;                 //parametr okreslajacy wielkosc napiecie wyjsciowego
                                        //^ obliczony na podstawie t_out i U_in
static unsigned int ocr0a, ocr0b, ocr1a;//zmienne pomocnicze do przechowywania obl. wypelnien
static unsigned int ocr1b, ocr2a, ocr2b;//^
static double sin_in;         //zmienna zawierajaca parametr funkcji sin
static double blad = 1;       //zmienna uzyta do zatrzymania generowania napiecia przy przeciazeniu 
static unsigned int analog=0; //zmienna zawierajaca zmierzona wartosc
static double U_in = 0;       //zmienna przechowujนca pomiar napiecia ukladu posredniczacego
static double U_rms_max;      //maksymalna aktualnie mozliwa do generacji wartosc skuteczna napiecia
static bool a=0;              //zmienna logiczna do realizacji dwoch naprzemiennych pomiarow 
int main() 
{
  io_init();     //inicjalizacja wejsc i wyjsc
  timers_init(); //inicjalizacja licznikow PWM 
  adc_init();    //inicjalizacja przetwornika ADC
  while(1)                                //nieskonczona petla z programem glownym
  {
    if(i==185)                            //warunek okreslajacy wejscie do funkcji zmiany 
    {                                     //parametrow napiecia wysjciowego, wywolanie co okolo 100ms
      zmien_predkosc();                   //funkcja zmiany parametrow napiecia wyjsciowego
      i=0;
    }
    next_value_sin = licznik_glowny%dlugosc_tab_sin;  //kolejna wartoœๆ sinusa do obliczenia
    sin_in=omega_t*next_value_sin;

//Расчет регистров значений, определяющих wyjscioweg сигнала заполнения/
    ocr0a = round(blad*(U_o_param*(sin(sin_in)+1)*254/2)+1);//pin 6
    ocr0b = ocr0a - 1;
    ocr1a = round(blad*(U_o_param*(sin(sin_in-2.09)+1)*254/2)+1);//pin 9
    ocr1b = ocr1a - 1;
    ocr2a = round(blad*(U_o_param*(sin(sin_in+2.09)+1)*254/2)+1);//pin 11
    ocr2b = ocr2a - 1;
      
//обновить значения в регистрах/
    cli();                              //запретить obsloge прервать в случае 
                                        //при обновлении прерывания
    OCR0A = ocr0a;    //pin 6
    OCR0B = ocr0b;    //pin 5
    OCR1AL = ocr1a;   //pin 9
    OCR1BL = ocr1b;   //pin 10
    OCR2A = ocr2a;    //pin 11
    OCR2B = ocr2b;    //pin 3
    sei();                              //zezwolenie na obsloge przerwan
    i++;
    }
}
void adc_init()
{ 
ADCSRA |= _BV(ADEN);//uruchomienie przetwornika
ADCSRA |= _BV(ADPS2);//ustawienie preskalera
ADCSRA |= _BV(ADPS1);//^
ADCSRA |= _BV(ADPS0);//^
ADMUX |= _BV(REFS0);// napiecie odniesienia ustawione jako napiecie zasilania
ADMUX |= ADMUX &= 0b11110000; //wybranie wejscia ADC0 do pomiaru
}
void timers_init()
{
cli();  // obsloga przerwan zabroniona
//timer0 init
TCCR0A |= _BV(COM0A1) | _BV(COM0B0) | _BV(COM0B1) | _BV(WGM00);               
TCCR0B |= _BV(CS01);              //preskaler 8
TIMSK0 |= _BV(TOIE0);             //flaga od wartosci 0 wlaczona
//timer1 init
TCCR1A |= _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1)  | _BV(WGM10);     
TCCR1B |= _BV(CS11);              //preskaler 8
//timer2 init
TCCR2A |= _BV(COM2A1) | _BV(COM2B0) | _BV(COM2B1)  | _BV(WGM20);     
TCCR2B |= _BV(CS21);              //preskaler 8
//Сброс значения licznik3w
TCNT0 = 0;
TCNT1L = 0;
TCNT2 = 0;
/* он считает g3re до 255, а затем на d3 ณ: / \ / \ / \
значение 255 прерывается, на котором выполняется августа
измерения напряжений и токов
*/
sei();  //zezwolenie na obsloge przerwan
}
void io_init()
{
  pinMode(6, OUTPUT); //OC0A
  pinMode(5, OUTPUT); //OC0B
  pinMode(9, OUTPUT); //OC1A
  pinMode(10, OUTPUT);//OC1B
  pinMode(11, OUTPUT);//OC2A
  pinMode(3, OUTPUT); //OC2B
  pinMode(2, INPUT);
  pinMode(4, INPUT);
  pinMode(12, OUTPUT); 
}
ISR(TIMER0_OVF_vect)  //прерывание значений 0 licznika0
{
    analog = ADC;
      if(a) 
      {
        U_in = 0.0709*analog;
        ADMUX |= _BV(MUX0);           //wybranie wejscia ADC1 do pomiaru pradu                                           
      }
      else 
      {
        ADMUX |= ADMUX &= 0b11110000; //wybranie wejscia ADC0 do pomiaru napiecia
        if(analog>579)            
        {
          blad = 0;               //jezeli przeciazenie wylaczenie generacji napiecia
          digitalWrite(12, HIGH); //zapalenie diody 
        }
      }
      ADCSRA |= _BV(ADSC);//start odczytywania pomiaru
      a=a^1;              //bramka XOR neguje wartosc logiczna a               
 licznik_glowny++;
 if(licznik_glowny>=dlugosc_tab_sin) licznik_glowny = 0;
} 
void zmien_predkosc()
{
  
  t_param = map(analogRead(3),0,1023,0,100);
  U_rms_max = U_in*0.62;  //wartosc 0.62 wyzanczona eksperymentalnie
  bool up;          //zmienna logiczna, informuje o nacisnietym przycisku zwieksz czestotliwosc
  bool down;        //zmienna logiczna, informuje o nacisnietym przycisku zmiejsz czestotliwosc
  up =  digitalRead(4);     //odczyt: czy nacisniety przycisk zwieksz czestotliwosc
  down = digitalRead(2);    //odczyt: czy nacisniety przycisk zmiejsz czestotliwosc
  if(up==1) t_param--;      //jezeli nacisniety przycisk zwieksz czestotliwosc to zmiejsz okres
  if(down==1) t_param++;    //jezeli nacisniety przycisk zmniejsz czestotliwosc to zwieksz okres
  if(t_param<0) t_param=0;    //zabezpieczenie przekroczenia wartosci skrajnych
  if(t_param>100) t_param=100;//^
  dlugosc_tab_sin = ceil((K_MAX-K_MIN)*t_param/500+K_MIN);//ilosc wartosci wypelnien w jednym okresie
  t_out = T_PWM*dlugosc_tab_sin;                          //obliczenie okresu napiecia wyjsciowego
  omega_t = t*2*PI/t_out;                                 //obliczenie pulsacji napiecia wyjsciowego
  U_o_param = (P/t_out)/U_rms_max;  //obliczenie parametru okreslajacego wielkosc napiecia wyjsciowego
  if(t_out>1) U_o_param = 0.5*(18.5/U_rms_max); //napi๊cie na wyjsciu przy niskiej czestotliwosci 10V
  if(U_o_param>1) U_o_param=1;  
  //zabezpieczenie przekroczenia wartosci skrajnych
    blad = 1;               //jezeli przeciazenie wylaczenie generacji napiecia
          digitalWrite(12, LOW); //zapalenie diody 
}

 

144
144 аватар
Offline
Зарегистрирован: 14.02.2016

Может быть название и страшное у этого скетча,но по сути он управляет миганием 6 диодов , частота изменяется резистором. Уже второй месяц ковыряю эту тему,лучше этого скетча не нашел ничего. Но у меня почему то не работает.

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Вот я одного не пойму. Почему вы не переведете комментарии на русский и вставите в программу.

ПС: зачем извращаться нарисуйте прогрограмму с помощью millis().

/*to_144.ino
  ключ + полуволны->2 (plus_pin) 0 закрыто /1 открыто
  ключ - полуволны->3 (minus_pin) 0 закрыто /1 открыто
*/
const uint32_t period = 100; // период 0,1 сек - частота 10 гц
const byte plus_pin = 2;
bool plus_ON ; // флаг открытия ключа+
const uint32_t T1 = 12; // время открытия ключа+
bool plus_OFF ; // флаг закрытия ключа+
const uint32_t T2 = 27; // время закрытия ключа+
const byte minus_pin = 3;
bool minus_ON ; // флаг открытия ключа-
const uint32_t T3 = 62; // время открытия ключа-
bool minus_OFF ; // флаг закрытия ключа-
const uint32_t T4 = 77; // время закрытия ключа-
void setup() {
  pinMode(plus_pin, OUTPUT);
  digitalWrite(plus_pin, 0);
  plus_ON = 0;
  plus_OFF = 0;
  pinMode(minus_pin, OUTPUT);
  digitalWrite(minus_pin, 0);
  minus_ON = 0;
  minus_OFF = 0;
}

void loop() {
  static uint32_t past = 0 ;
  if (millis() - past >= period) { // если прошeл период
    past = millis() ;
    plus_ON = 1;
    minus_ON = 1;
  }
  if (plus_ON && millis() - past >= T1) { // если подошло время включить ключ +
    plus_ON = 0;
    plus_OFF = 1;
    digitalWrite(plus_pin, 1);
  }
  if (plus_OFF && millis() - past >= T2) {// если подошло время выключить ключ +
    plus_OFF = 0;
    digitalWrite(plus_pin, 0);
  }
  if (minus_ON && millis() - past >= T3) {// если подошло время включить ключ -
    minus_ON = 0;
    minus_OFF = 1;
    digitalWrite(minus_pin, 1);
  }
  if (minus_OFF && millis() - past >= T4) {// если подошло время выключить ключ -
    minus_OFF = 0;
    digitalWrite(minus_pin, 0);
  }
}

 

144
144 аватар
Offline
Зарегистрирован: 14.02.2016

дак а где я задержки возьму? и какую обмотку когда какую полярность подавать? 

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

144 пишет:

дак а где я задержки возьму? и какую обмотку когда какую полярность подавать? 

Если бы вы сказали , где бы вам мозги взять, то бы не так удивился. Вы что не знаете, что такое переменный ток, что такое синус.  

Цитата:

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

Ну мозги есть не только у полякоговорящих.http://electrono.ru/elektricheskie-mashiny/vrashhayushheesya-magnitnoe-pole

http://electrono.ru/3-invertory-napryazheniya-i-toka-energ_electr

144
144 аватар
Offline
Зарегистрирован: 14.02.2016

Я конечно новичок на этом форуме. Но я не просил лекцию по электротехнике. А просил подсказать как скетч исправить,а если мозгов не хватает это понять,то наверное не надо спамить. Мне не надо мериться умами,мне надо решить проблему.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну ладно, "походите по рынку". Я вам дал все для понимания, но если пациент хочет в морг, то врач тут бессилен.

144
144 аватар
Offline
Зарегистрирован: 14.02.2016

qwone пишет:

Ну ладно, "походите по рынку". Я вам дал все для понимания, но если пациент хочет в морг, то врач тут бессилен.

Да, я понял уже что ты "спец". Можешь дальше не пыжиться.

Если мне надо будет ходить по рынку,то ты будешь последний к кому я подойду. И вообще если ходить по рынку на нафиг надо ардуино и этот форум?  Я просто закажу у нормального чувака плату и он мне её сделает,под мои хотелки. 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Пишет : exit status 1

Проверил У меня он компилируется. Arduino 1.6.10. Попробуйте сменить IDE

nik182
Offline
Зарегистрирован: 04.05.2015

Этот скеч будет работать на меге. Ну или с некоторыми натяжками на леонарде или мини. Uno & nano не будут работать. А вообще для данной задачи лучше подходит stm32.  У него первый таймер имеет режим генерации трёхфазного управления мотором и входной делитель позволяет плавно менять частоту. На AVR плавного изменения частоты не получится.

144
144 аватар
Offline
Зарегистрирован: 14.02.2016

vosara пишет:

Пишет : exit status 1

Проверил У меня он компилируется. Arduino 1.6.10. Попробуйте сменить IDE

Большое спасибо за ответ! А как мне сменить IDE ? В интернете есть видео где он работает даже на Ардуино Микро.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

144 пишет:

А как мне сменить IDE ?


Зайти на официальный сайт проекта Arduino и скачать оттуда.

144
144 аватар
Offline
Зарегистрирован: 14.02.2016

Спасибо всем кто откликнулся!

Не было времени ответить раньше.

Смена IDE помогла,всё загрузилось и работает. Осталось подключить к IGBT модулю,но это уже другая задача.