Étape 3: Le code
/***
AFFECTATION DES BROCHES SUR ATMEGA48
PC6 (PCINT14/RESET)
PC5 (ADC5/SCL/PCINT13) / / entrée horloge I2C
PC4 (SDA/ADC4/PCINT12) / / entrée de données I2C
Récepteur IR de PC3 (ADC3/PCINT11) //Sensor 4
Récepteur IR de PC2 (ADC2/PCINT10) //Sensor 3
Récepteur IR de PC1 (ADC1/PCINT9) //Sensor 2
Récepteur IR de PC0 (ADC0/PCINT8) //Sensor 1
PB7 (PCINT7/XTAL2/TOSC2) //IR 4 déclencher
PB6 (PCINT6/XTAL1/TOSC1) //IR 3 déclencher
PB5 (SCK/PCINT5) //IR 2 déclencher
PB4 déclencher (MISO/PCINT4) //IR 1
PB3 (MOSI/OC2A/PCINT3) //PWM 3
PB2 (SS/OC1B/PCINT2)
PB1 (OC1A/PCINT1)
PB0 (PCINT0/CLKO/ICP1)
PD0 (PCINT16/RXD)
PD1 (PCINT17/TXD)
PD2 (PCINT18/INT0)
PD3 (PCINT19/OC2B/INT1) //PWM 4
PD4 (PCINT20/XCK/T0)
PD5 (PCINT21/OC0B/T1) //PWM 2
PD6 (PCINT22/OC0A/AIN0) //PWM 1
PD7 (PCINT23/AIN1)
***/
#define IR_1_ON PORTB | = (1 << 4)
#define IR_2_ON PORTB | = (1 << 5)
#define IR_3_ON PORTB | = (1 << 6)
#define IR_4_ON PORTB | = (1 << 7)
#define IR_1_OFF PORTB & = ~ (1 << 4)
#define IR_2_OFF PORTB & = ~ (1 << 5)
#define IR_3_OFF PORTB & = ~ (1 << 6)
#define IR_4_OFF PORTB & = ~ (1 << 7)
#define PWM1 6 //PORTD PWM pin affectations
#define PWM2 5 //PORTD
#define PWM3 //PORTB 3
#define PWM4 3 //PORTD
#define F_CPU 8000000UL
#include
#include
#include
#include
/ *** Fonction déclarations *** /
int ADC_read(void) ;
void A2D_Channel_Select (unsigned canal char) ;
void Init_ADC(void) ;
void Init_Timer0(void) ;
void Init_Timer1(void) ;
void Init_Timer2(void) ;
void Delay(void) ;
void Calibrate_Sensors(void) ;
void Init_I2C_Slave_Rx(void) ;Tous, sauf un, de ces variables est déclarée volatile car fondamentalement tout le travail se fait en
routines d’interruption service
/ *** Déclarations de Variable globale *** / tampons d’unsigned char = 8 ; int main (void) SEI() ; PORTD | = (1 << PWM1) ; clignote pour indiquer la fin d’étalonnage Init_Timer0() ; Init_I2C_Slave_Rx() ; while(1) }
volatils char Sensor_Values_Updated = 0 ;
volatils char Timer1_Overflow = 0 ;
canal de volatiles unsigned char = 0 ;
volatile int Amb_Sensor_1 = 0, Amb_Sensor_2 = 0, Amb_Sensor_3 = 0, Amb_Sensor_4 = 0 ;
volatile int Sensor_1 = 0, Sensor_2 = 0, Sensor_3 = 0, Sensor_4 = 0 ;
volatile int Initial_1 = 0, Initial_2 = 0, Initial_3 = 0, Initial_4 = 0 ;
volatile int New_PWM1 = 0, New_PWM2 = 0, New_PWM3 = 0, New_PWM4 = 0 ;
volatile int Old_PWM1 = 0, Old_PWM2 = 0, Old_PWM3 = 0, Old_PWM4 = 0 ;
{
DDRB = 0XFF ;
Veillez à ce que les émetteurs IR sont éteints et 3 PWM
PORTB & = ~ ((1 << 7) | () 1 << 6) | (1 << 5) | (1 << 4) | (1 << 3)) ;
DDRC = 0 X 00 ; faire les entrées du PORT C
DDDR = 0XFF ;
PORTD = 0 X 00 ; Définissez tous PORT D faible. veille à ce
Init_ADC() ;
Calibrate_Sensors() ;
_delay_ms(600) ;
PORTD & = ~ (1 << PWM1) ;
Init_Timer2() ;
{
faire quelque chose ?
//. . .
}
Avec l’horloge fonctionnant à environ 8MHz et 1 Timer comptant jusqu'à 65535. La minuterie débordera environ 122 fois par seconde. Ce rapport de recherche internationale se déclenche et s’incrémente la variable de débordement du timer, et ensuite la fonction SWITCH/CASE choisira le pixel suivant pour tester
ISR(TIMER1_OVF_vect)
{
Timer1_Overflow ++ ; variable de débordement timer incrément
Switch(Timer1_Overflow)
{
cas 1 :
A2D_Channel_Select(0) ; Sélectionnez ADC canal 0
Amb_Sensor_1 = ADC_read() ; prendre la lecture de capteur IR ambiante
IR_1_ON ; allumer la LED IR 1, PORTB | = (1 << 4)
Delay() ; délai pour le récepteur IR à régler
Sensor_1 = ADC_read() ; ADC active de prendre lecture du récepteur IR
IR_1_OFF ; Mettez hors tension IR 1 LED
New_PWM1 = (Sensor_1 - Amb_Sensor_1) - Initial_1 ; lectures de condition
Si (New_PWM1 < = 0) {New_PWM1 = 0;} éviter les nombres négatifs
simple filtre passe-bas, (87,5 % * vieux) + (12,5 % * New) . Il faut juste l’ancienne valeur et le poids plus que l’ancienne valeur. A le même effet de ralentir le changement, ce qui est essentiel dans la fourniture de fluides changements de luminosité
New_PWM1 = ((7*Old_PWM1) >> 3) + (New_PWM1 >> 3) ;
Si (OCR0A > = 1) {DDDR | = (1 << PWM1);}
else {DDDR & = ~ (1 << PWM1);} désactiver complètement les LEDs//artificially, augmentez la valeur du capteur lire, pas tout à fait nécessaire, mais rend le capteur semblent plus sensiblesen étant plus clair plus tôt
New_PWM1 << = 2 ;
if(New_PWM1 > 255) {New_PWM1 = 255;}
OCR0A = New_PWM1 ;
New_PWM1 >> = 2 ;
Le code qui est entièrement commenté ci-dessous est un algorithme de luminosité différente. Il s’agit d’un algorithme déclenchement qui se dissipera les LEDs quand quelque chose vient au sein d’un seuil. Et les LEDs seront fane dehors lentement lorsque l’objet est hors de la distance du seuil. Ceci est utile parce que l’opération pourrait être plus fiable et le fondu le temps peut être ajusté pour être très long ou toutefois depuis longtemps vous le voulez. Je n’ai pas testé ce code donc je ne sais pas si cela va fonctionner à 100 %
/ *** //Trigger séquence if(OCR0A < 255)
if(New_PWM1 > Initial_1)
{
DDDR | = (1 << PWM1) ;
{
OCR0A += (255 - OCR0A) >> 2 ;
OCR0A ++ ;
}
Si (New_PWM1 < (Initial_1 + 8))
{
Initial_1 = ((7*Initial_1) >> 3) + (New_PWM1 >> 3) ;
}
}
d’autre if(New_PWM1 < Initial_1)
{
if(OCR0A > 0)
{
OCR0A-= (OCR0A >> 4) + 1 ;
OCR0A--;
}
ElseIf (OCR0A < = 0)
{
DDDR & = ~ (1 << PWM1) ;
}
}
*****/
Old_PWM1 = New_PWM1 ;
rupture ;
cas 2 :
A2D_Channel_Select(1) ; Sélectionnez le canal ADC 1
Amb_Sensor_2 = ADC_read() ;
IR_2_ON ; allumer la LED IR 2, PORTB | = (1 << 5)
Delay() ; délai pour le récepteur IR à régler
Sensor_2 = ADC_read() ; prendre ADC lire
IR_2_OFF ; éteindre la LED 2 IR
New_PWM2 = (Sensor_2 - Amb_Sensor_2) - Initial_2 ;
if(New_PWM2 < 0) {New_PWM2 = 0;}
New_PWM2 = ((7*Old_PWM2) >> 3) + (New_PWM2 >> 3) ;
Si (OCR0B > = 1) {DDDR | = (1 << PWM2);}
else {DDDR & = ~ (1 << PWM2);}
New_PWM2 << = 2 ;
if(New_PWM2 > 255) {New_PWM2 = 255;}
OCR0B = New_PWM2 ;
New_PWM2 >> = 2 ;
/*
if(New_PWM2 > Initial_2)
{
DDDR | = (1 << PWM2) ;
if(OCR0B < 255)
{
OCR0B += (255 - OCR0B) >> 2 ;
OCR0B ++ ;
}
Si (New_PWM2 < (Initial_2 + 8))
{
Initial_2 = ((7*Initial_2) >> 3) + (New_PWM2 >> 3) ;
}
}
d’autre if(New_PWM2 < Initial_2)
{
if(OCR0B > 0)
{
OCR0B-= (OCR0B >> 4) + 1 ;
OCR0B--;
}
ElseIf (OCR0B < = 0)
{
DDDR & = ~ (1 << PWM2) ;
}
}
*/
Old_PWM2 = New_PWM2 ;
rupture ;
cas 3 :
A2D_Channel_Select(2) ; sélectionner le canal de l’ADC 2
Amb_Sensor_3 = ADC_read() ;
IR_3_ON ; allumer la LED IR 3, PORTB | = (1 << 6)
Delay() ; délai pour le récepteur IR à régler
Sensor_3 = ADC_read() ; prendre ADC lire
IR_3_OFF ; Mettez hors tension IR 3 LED
New_PWM3 = (Sensor_3 - Amb_Sensor_3) - Initial_3 ;
if(New_PWM3 < 0) {New_PWM3 = 0;}
New_PWM3 = ((7*Old_PWM3) >> 3) + (New_PWM3 >> 3) ;
Si (OCR2A > = 1) {DDRB | = (1 << PWM3);}
else {DDRB & = ~ (1 << PWM3);}
New_PWM3 << = 2 ;
if(New_PWM3 > 255) {New_PWM3 = 255;}
OCR2A = New_PWM3 ;
New_PWM3 >> = 2 ;
/*
if(New_PWM3 > Initial_3)
{
DDRB | = (1 << PWM3) ;
if(OCR2A < 255)
{
OCR2A += (255 - OCR2A) >> 2 ;
OCR2A ++ ;
}
Si (New_PWM3 < (Initial_3 + 8))
{
Initial_3 = ((7*Initial_3) >> 3) + (New_PWM3 >> 3) ;
}
}
d’autre if(New_PWM3 < Initial_3)
{
if(OCR2A > 0)
{
OCR2A-= (OCR2A >> 4) + 1 ;
OCR2A--;
}
ElseIf (OCR2A < = 0)
{
DDRB & = ~ (1 << PWM3) ;
}
}
*/
Old_PWM3 = New_PWM3 ;
rupture ;
cas 4 :
A2D_Channel_Select(3) ; Sélectionnez ADC canal 3
Amb_Sensor_4 = ADC_read() ;
IR_4_ON ; allumer la LED IR 4, PORTB | = (1 << 7)
Delay() ; délai pour le récepteur IR à régler
Sensor_4 = ADC_read() ; prendre ADC lire
IR_4_OFF ; Mettez hors tension IR 4 LED
New_PWM4 = (Sensor_4 - Amb_Sensor_4) - Initial_4 ;
if(New_PWM4 < 0) {New_PWM4 = 0;}
New_PWM4 = ((7*Old_PWM4) >> 3) + (New_PWM4 >> 3) ;
Si (OCR2B > = 1) {DDDR | = (1 << PWM4);}
else {DDDR & = ~ (1 << PWM4);}
New_PWM4 << = 2 ;
if(New_PWM4 > 255) {New_PWM4 = 255;}
OCR2B = New_PWM4 ;
New_PWM4 >> = 2 ;
/*
if(New_PWM4 > Initial_4)
{
DDDR | = (1 << PWM4) ;
if(OCR2B < 255)
{
OCR2B += (255 - OCR2B) >> 2 ;
OCR2B ++ ;
}
Si (New_PWM4 < (Initial_4 + 8))
{
Initial_4 = ((7*Initial_4) >> 3) + (New_PWM4 >> 3) ;
}
}
d’autre if(New_PWM1 < Initial_4)
{
if(OCR2B > 0)
{
OCR2B-= (OCR2B >> 4) + 1 ;
OCR2B--;
}
ElseIf (OCR2B < = 0)
{
DDDR & = ~ (1 << PWM4) ;
}
}
*/
Old_PWM4 = New_PWM4 ;
Timer1_Overflow = 0 ; remise à zéro
Sensor_Values_Updated = 1 ; prêt de nouvelles valeurs
rupture ;
} //end commutateur
} //end ISR
C’est quelque chose que je vais essayer et trouver plus tard. C’est non testé code élémentaire qui pourrait me permettre d’utiliser l’Interface de fils deux (I2C) si plusieurs contrôleurs et communiquent entre eux ou avoir un maître et un tas d’esclaves.
/****
ISR(TWI_vect) //to inclure plus tard quand j’ai obtenu ceci figuré dehors
{
Switch(TWSR)
{
affaire TW_SR_SLA_ACK : //0x60 //Own adresse Rx
Byte_Number == 1 ;
rupture ;
case TW_SR_DATA_ACK: / / 0 x 80, données à TWDR
Switch(Byte_Number)
{
cas 1 :
Reg_Addr = TWDR ;
Byte_Number ++ ;
rupture ;
cas 2 :
Reg_Val = TWDR ;
Byte_Number = 0 ; remis à zéro, à moins que davantage d’octets est à venir
rupture ;
affaire Max_Bytes_Expected :
Reg_Val = TWDR ;
Byte_Number = 0 ; remis à zéro, à moins que davantage d’octets est à venir
rupture ;
}
rupture ;
case TW_SR_GCALL_DATA_ACK: / / 0x90
if(Byte_Number == 1)
{
Reg_Addr = TWDR ;
Byte_Number ++ ;
}
d’autre if(Byte_Number == 2)
{
Reg_Val = TWDR ;
Byte_Number = 0 ; remis à zéro, à moins que davantage d’octets est à venir
}
rupture ;
} //end commutateur
} //end ISR
Sub Init_I2C_Slave_Rx(void)
{
Adresse du périphérique figurant de TWAR
TWAR = 10 ; peut-être faire cela en tant qu’argument à cette fonction
CONFIRM | = ((1 << TWEA) | () 1 << TWEN)) ;
Confirm & = ~ ((1 << TWSTA) | () 1 << TWSTO)) ;
}
****/
Sub Calibrate_Sensors(void) //establish valeurs de capteur ambiant initial
{
char q = 0 ;
Init_Timer1() ;
pour (q = 0; q < 32; q ++) //should prendre un second-ish
{
Attendez que le programme de détection à faire, puis rassembler les valeurs capteurs
while(Sensor_Values_Updated == 0) {}
Initial_1 += (Sensor_1 - Amb_Sensor_1) ; différence initiale
Initial_2 += (Sensor_2 - Amb_Sensor_2) ;
Initial_3 += (Sensor_3 - Amb_Sensor_3) ;
Initial_4 += (Sensor_4 - Amb_Sensor_4) ;
Sensor_Values_Updated = 0 ; remise à zéro
} //end pour
valeurs de //condition de capteur ambiant initial, plus un tampon Sub Init_ADC(void) void Init_Timer0(void) //PWM pour capteurs 1 & 2 int ADC_read(void) / *** sélectionnez ADC canal avant d’appeler cette fonction *** /
Initial_1 = (Initial_1 >> 5) + tampon ;
Initial_2 = (Initial_2 >> 5) + tampon ;
Initial_3 = (Initial_3 >> 5) + tampon ;
Initial_4 = (Initial_4 >> 5) + tampon ;
}
{
ADMUX | = 1 << REFS0 ; AVCC avec condensateur externe sur la broche AREF
ADMUX | = (1 <
}
{
Rapide de PWM, non inversé, WGM02-WGM00 == 011, sans interruption de débordement
TCCR0A | = ((1 << COM0A1) | () 1 << COM0B1) | (1 << WGM01) | (1 << WGM00)) ;
TCCR0B | = (1 << CS00) ; démarrer l’horloge, sans Prédiviseur
}
Sub Init_Timer1(void)
{
aucun PWM, activer interruption de débordement,
TOP == 0xFFFF == 65536 cycles == environ 122 débordement interruptions/s
TCCR1B | = (1 << CS10) ;
TIMSK1 | = (1 << TOIE1) ;
}
void Init_Timer2(void) //PWM pour capteurs 3 & 4
{
Rapide de PWM, non inversé, WGM22-WGM20 == 011, sans interruption de débordement
TCCR2A | = ((1 << COM2A1) | () 1 << COM2B1) | (1 << WGM21) | (1 << WGM20)) ;
TCCR2B | = (1 << CS20) ; démarrer l’horloge, sans Prédiviseur
}
{
int ADC_value = 0 ;
int ADCsample ;
char i ;
ADCSRA | = (1 < ADCSRA | = (1 < while ((ADCSRA & ADSC)) ; Attendez de conversion compléter et oubliez-le
//This se fait pas plus de 64 fois, plus et ADC1_value devront être plus grand qu’un unsigned int!!!
pour (i = 0; i < 64; i ++)
{
ADCSRA | = (1 < while ((ADCSRA & ADSC)) ; attendre que la conversion à la fin
//change retour à ADCL pour 10 bits de précision et supprimer le paramètre de bits de décalage vers la gauche
ADCsample = ADCH ;
ADCsample += (ADCH << 8) ; Décalage à gauche les deux bits supérieurs 8 places
ADC_value += ADCsample ; Ajouter ADCsample à ADC_sensor
}
un échantillon moyen de droit déplacement 6 places, même en divisant par 64
ADC_value = (ADC_value >> 6) ;
Return ADC_value ;
ADCSRA & = ~(1<
void A2D_Channel_Select (canal unsigned char)
{
commutateur (canal)
{
case 0: //select A2D canal 0
ADMUX & = ~ ((1 << 3) | () 1 << 2) | (1 << 1) | (1 << 0)) ;
rupture ;
cas 1: //select A2D canal 1
ADMUX & = ~ ((1 << 3) | () 1 << 2) | (1 << 1)) ;
ADMUX | = (1 << 0) ;
rupture ;
cas 2: //select A2D canal 2
ADMUX & = ~ ((1 << 3) | () 1 << 2) | (1 << 0)) ;
ADMUX | = (1 << 1) ;
rupture ;
case 3: //select A2D canal 3
ADMUX & = ~ ((1 << 3) | () 1 << 2)) ;
ADMUX | = ((1 << 1) | () 1 << 0)) ;
rupture ;
/ * je ne suis pas en utilisant ceux-ci pour ce projet
case 4: //select A2D canal 4
ADMUX & = ~ ((1 << 3) | () 1 << 1) | (1 << 0)) ;
ADMUX | = (1 << 2) ;
rupture ;
cas 5: //select A2D canal 5
ADMUX & = ~ ((1 << 3) | () 1 << 1)) ;
ADMUX | = ((1 << 2) | () 1 << 0)) ;
rupture ;
*/
} //end commutateur
}
Sub Delay(void)
{
_delay_us(100) ;
}