Eto sveža rutina za branje 24 analognih vhodov z Unotom in to v ozadju (IRQ) s filtrom 50Hz. V glavni zanki teče samo čakanje na konec zajema vseh 24 kanalov in izpis rezultatov (vsakih cca 5s). Tu je še pretvorba v temperaturo z NTC upori, ki pa je zakomentirana.
Morda AD vhodi na strani Atmela niso 100% v pravem zaporedju, ker sem testiral z enim samim 4051 in so bili vhodi v proc (AD3 do 5) vezani vzporedno.
//Na Uno izhodi A0 do A2 krmilijo 3 multiplexerje HC4051, katerih izhodi so vezani na A3 do A5
//Na ta način dobimo 24 vhodov.
//AD konverter teče z avtomatskim proženjem ob koncu prejšnje konverzije, pri čemer se sproži interrupt, v katerem se zamenjata notranji in zunanji MUX
//Da se eliminira motnja iz omrežja in drugi prehodni pojavi, se za vsak kanal naredi 2500 meritev.
//To traja 39 period omrežne frekvence oziroma 780ms
//Na vhode lahko priključimo že omenjene NTC-je in sicer preko 8K25 na +5V. Program iz tabele izračuna temperaturo in jo izpiše na Serial
#define MuxA A0
#define MuxB A1
#define MuxC A2
const byte AnRef= 64; //Leonardo 64 5V ref 192 interna 2,5V ref
long adcReadTemp[24];
long adcReading[24];
byte adcExtMux = 1; //Zato da interupt rutina ADC-ja čim hitreje nastavi externi Mux in šele nato naredi increment
//AD readings * 10 for -40...130°C
//+5V_8K25_ADIn_NTC_GND
word NTC_Table[]={9805,9702,9566,9381,9161,8903,8606,8270,7896,7487,7048,6584,6101,5605,5108,
4626,4168,3738,3341,2978,2649,2353,2089,1854,1646,1462,1300,1158,1032,922,825,739,663,597,538};
const byte TabLen = sizeof(NTC_Table)/2-1;//-1 da ni treba v while odštevat
//korekcija za 2 priključena NTC-ja, za več podaljšaj konstanto
float TempCor[] = {0, -0.3};
volatile boolean adcDone = false;
boolean adcStarted;
long sensorValue = 0;
//Mux tabela za Unota
byte AD_Kanali[] = {5, 3, 4};//Zamik kanalov zaradi narave IRQ rutine
byte MuxIndex=0;
word itIndex=0;
byte i;
void setup ()
{
pinMode(MuxA, OUTPUT);
pinMode(MuxB, OUTPUT);
pinMode(MuxC, OUTPUT);
digitalWrite(MuxA, HIGH);
digitalWrite(MuxB, LOW);
digitalWrite(MuxC, LOW);
PORTC = 0; //Nastavi externi Mux na 0;
// start serial port
Serial.begin(19200);
ADMUX = AnRef+AD_Kanali[0];
// start the conversion
ADCSRA |= _BV (ADSC) | _BV (ADIE) | 32;
// Start up the library
} // end of setup
// ADC complete ISR
ISR (ADC_vect)
{
byte low, high;
byte ADC_Index;
low = ADCL;
high = ADCH;
ADMUX = AnRef+AD_Kanali[MuxIndex];
ADC_Index = MuxIndex + (3 * (adcExtMux-1));
adcReadTemp[ADC_Index] = adcReadTemp[ADC_Index]+((high << 8) | low);
MuxIndex++;
if (MuxIndex >2)
{
if (itIndex > 2499)
{
//adcExtMux = 7 && ++adcExtMux;
if (adcExtMux == 8){
PORTC = 0;
adcExtMux = 1;
memcpy(adcReading,adcReadTemp,96);
for (int i=0; i < 24; i++)
adcReadTemp[i] = 0;
adcDone = true;
}
else PORTC = adcExtMux++;
itIndex = 0;
}
MuxIndex=0;
itIndex++;
}
} // end of ADC_vect
void loop ()
{
if (adcDone){
for (int n=0; n<24; n++){
//ADCx10 je povprečje odčitkov AD-ja pomnoženo z 10 zaradi večje točnosti
word ADCx10 = (adcReading[n]+249) / 250;//+249 zaradi napake ADja na spodnjem koncu
Serial.print(ADCx10);
Serial.print(" ");
/*
i = 1;
while((ADCx10 <= NTC_Table[i])&(i<TabLen)){
i++;
}
if (ADCx10 >= NTC_Table[i]){
int T = -40+i*5;
Serial.print(T-5.0*(ADCx10 - NTC_Table[i])/(NTC_Table[i-1]-NTC_Table[i])+TempCor[n]);
Serial.print("C ");
}
else{
Serial.print("Napaka, odcitek AD-ja ");
Serial.print(ADCx10/10);
Serial.print(", morda je temperatura >130C ");
}
*/
}
Serial.println("");
adcDone = false;
}
delay(200);
} // end of loop