หากเรามองจาก ท้องฟ้า เราจะเห็น สิ่งที่เคลื่อนไหว ภายใต้ ของความคิดเรา ถ้าเรามองขึ้นไปจากใจเรา เราจะเห็น ทุกชีวิต กำลังดิ้นรน เพื่อ แสวงหา อาหาร เพื่อ หล่อเลี้ยง ชีวิตของตนเอง และ สิ่งที่ตนรัก และเป็นที่รัก ของตนเอง และแล้ว ทุกชีวิต ก็ พบว่า ความกระหายใคร่ ได้ ใคร่มี ใคร่เป็น หรือ ความทะยานอยาก นี่เอง ที่เป็นสาเหตุ ให้มนุษย์ ต้องเดินทางอยู่ ตลอดชีวิต ลองหยุดเดินทางด้วยยานพาหนะ แล้วหันมาเดินทาง ด้วยจิตวิญญาณ แล้วการ เดินทางไกล จะใกล้เข้าทุกขณะจิต หายใจเข้า ตามรู้ หายใจออก ตามรู้
วันจันทร์ที่ 13 กุมภาพันธ์ พ.ศ. 2560
การสร้างเครื่องควบคุมความเร็ว direct drive motor
//a simple demo software for small 3-phase inverter
//Danijel Gorupec, 2015
#include <avr/io.h>
#include <avr/interrupt.h>
char sin_table[64]=
{
0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45,
48, 51, 54, 57, 59, 62, 65, 67, 70, 73, 75, 78, 80, 82, 85, 87,
89, 91, 94, 96, 98, 100,102,103,105,107,108,110,112,113,114,116,
117,118,119,120,121,122,123,123,124,125,125,126,126,126,126,126,
};
unsigned char pwm_table[256]; //holds V-F curve adjusted PWM outputs
unsigned char speed; //output frequency (uint: 0.25Hz)
unsigned char direction; //rotation direction (0 forwared, 1 reverse)
unsigned int phase; //the phase of output sine signal
//some handy macros
#define LED_ON {SREG&=0x7F;PORTC|=0x10;SREG|=0x80;}
#define LED_OFF {SREG&=0x7F;PORTC&=0xEF;SREG|=0x80;}
#define INVERTOR_ENABLE {PORTC|=0x20;PORTD|=0x03;}
#define INVERTOR_DISABLE {PORTC&=0xDF;PORTD&=0xFC;}
#define INPUT_JOG ((PINC&0x02)==0)
#define INPUT_RUN ((PINC&0x04)==0)
#define INPUT_DIR ((PINC&0x08)==0)
#define JOG_SPEED 20
//timer interrupt routing
//It is called in fixed intervals. It advances sine wave phase.
ISR (TIMER0_OVF_vect)
{
if (direction==0)
phase+=speed; //phase: 0...16384 equals 0...2*pi
else
phase-=speed;
unsigned int p=phase/64;
unsigned char p1=p%256;
unsigned char p2=p1+85;
unsigned char p3=p1+171;
OCR1A=pwm_table[p1];
OCR1B=pwm_table[p2];
OCR2=pwm_table[p3];
//adjust the next timer interrupt time
TCNT0=256-240;
}
//this function makes a short pause
//time uint: about 10 microseconds (100 = 1 millisecond)
void WaitLoop(unsigned int time)
{
unsigned int i,j;
for (j=0;j<time;j++)
{
for (i=0;i<8;i++) //the ATmega is runs at 8MHz
if (PORTC==0xFF) DDRB|=0x02; //just a dummy instruction
}
}
char analog_channel=0;
void ReadAnalogs(void)
{
if (ADCSRA&(1<<ADSC)) {return;} //the conversion still not finished
if (analog_channel==0)
{
//ADCH is the speed reference (but inverted!!! - 255=min speed, 0=max speed)
unsigned char spd_ref=255-ADCH;
if (INPUT_JOG) spd_ref=JOG_SPEED;
if (INPUT_DIR)
{
if (direction==0) spd_ref=10;
if (speed==10) direction=1; //only allow direction change at minimum speed
}
else
{
if (direction==1) spd_ref=10;
if (speed==10) direction=0; //only alow direction change at minimum speed
}
if (spd_ref>speed) speed++;
if (spd_ref<speed) speed--;
if (speed<10) speed=10; //the minimum speed
//in next reading we again read this channel because there are no other analog channels used
analog_channel=0;
ADMUX=0x60;
}
ADCSRA|=(1<<ADSC);
}
int main()
{
//Set ATmega8 fuses to 8MHz, internal RC
//Hardware cosist of ATMega8 microcontroller, 6xIRF840 MOSFET (3 halfbridges)
//wait a bit, cca 300ms, for easier programming
//(otherwise programmer has problems downloading)
WaitLoop(30000);
//program IO pins of the ATMega8 microcontroller
//D0 - reset hold (can be kept high to ensure high level on reset pin C6)
//D1 - not used
//D2 - not used
//D3 - not used
//D4 - not used
//D5 - not used
//D6 - not used
//D7 - not used
DDRD=(unsigned char)0x00;
//B0 - not used (ICR1 is modified if this bit is changed)
//B1 - PWM_R
//B2 - PWM_S
//B3 - PWM_T (MOSI SPI)
//B4 - not used (MISO SPI)
//B5 - not used (SCK SPI)
//B6 - not used (always +5V)
//B7 - not used
DDRB=(unsigned char)0x0E;
//C0 - programable input 1 (speed reference - inverted analog input, +5V=min speed, 0V=max speed)
//C1 - programable input 2 (jog - digital input, active low)
//C2 - programable input 3 (run signal - digital input, active low)
//C3 - programable input 4 (rotation direction - digital input, active low)
//C4 - LED output
//C5 - enable output
//C6 - RESET
DDRC=(unsigned char)0x30;
//enable pull-up resistors on inputs 1, 2, 3 & 4
//note: this is nasty, it would be better if we have external pull-down resistors for analog inputs
// because now we have to use analog input in inverted way (+5V=min speed, 0V=max speed) so that
// the motor slows down if the wire disconnects
PORTC|=0x0F;
INVERTOR_DISABLE;
//LED test (0.3 sec)
LED_ON;
WaitLoop(30000);
LED_OFF;
//configuring ADC (trigger mode)
ADMUX=0x60; //AVcc for reference, right aligned, mux=ADC0
ADCSRA=0xC7; //ADC frequency (62.5kHz), results in 4.8kHz sampling rate
//wait one more milisecond
WaitLoop(100);
//Programming PWM_R and PWM_S
OCR1A=0x00;
OCR1B=0x00;
TCCR1A=0xA1; //OC1A and OC1B used, phase correct PWM, 8bit
TCCR1B=0x01; //1:1 prescaller - 15kHz PWM
//Programming PWM_T
OCR2=0x00;
TCCR2=0x61; //phase correct PWM, no prescaller - 15kHz PWM
//configuring timer 0
TCNT0=0x00; //timer set to start value
TCCR0|=0x02; //timer/counter 0 input frequency divider set to /8 (that is, 1MHz)
TIMSK|=0x01; //timer/counter 0 interrupt enabled
SREG|=0x80; //global interrupt enabled
speed=10; //2.5 Hz
//OCR1A=128;
//OCR1B=128;
//OCR2=128;
unsigned char led_cntr=0;
while (1)
{
int i;
if ((INPUT_RUN) || (INPUT_JOG))
{
if (led_cntr>16) LED_OFF else LED_ON //we just make short blinks to save power
led_cntr++;
//The VFfactor defines VF curve (how V depends on speed)
int VFfactor=(int)speed+18; //This setting is for asynchronous motor in delta connection (230VAC delta / 400VAC star)
//int VFfactor=speed/4+15; //this settign is for 200VAC servo motor with permanent magnet
if (VFfactor>255) VFfactor=255;
//computing PWM ratios (as we have nothing else to do, this is not optimized)
for (i=0;i<64;i++)
{
int A=sin_table[i];
if (A>127) A=-256+A; //wow! how come I cannot cast char to int?
A=A*VFfactor;
A=A/256;
A+=128+6;
if (A>250) A=250; //because signal delay, we cannot actually create very short impulses
SREG&=0x7F;
pwm_table[i]=A;
pwm_table[127-i]=A;
SREG|=0x80;
A=255-A;
SREG&=0x7F;
pwm_table[i+128]=A;
pwm_table[255-i]=A;
SREG|=0x80;
}
INVERTOR_ENABLE;
}
else
{
INVERTOR_DISABLE;
OCR1A=128;
OCR1B=128;
OCR2=128;
for (i=0;i<255;i++)
{
SREG&=0x7F;
pwm_table[i]=128;
SREG|=0x80;
}
led_cntr=0;
LED_OFF;
speed=10;
}
ReadAnalogs();
}
}
สมัครสมาชิก:
ส่งความคิดเห็น (Atom)
ไม่มีความคิดเห็น:
แสดงความคิดเห็น