Tiedote ylläpidolta:

Elektroniikkafoorumi sulkeutuu tietoturva ongelmien takia.
Käyttäjien tietoja (yv:t, sähköpostiosoite ja salasanan hash) on saattanut vuotaa vääriin käsiin.

Foorumi on asettettu vain luku tilaan. Vanhoja keskusteluja voi lukea palvelinsopimuksen päättymiseen asti.
Tietokannasta on poistettu kaikki salasanat, sähköpostiosoitteet ja yksityisviestit.

Jos haluat saada omat yksityisviestisi, lähetä sähköpostia yllapito@elektroniikkafoorumi.com
samasta sähköpostista mikä oli foorumin tiedoissa niin voin kaivella niitä varmuuskopioista.

Mielenkiintoni foorumin ylläpitoon on viime vuosina ollut vähäistä jo muutenkin joten tähän on hyvä lopettaa.
Kiitokset kaikille käyttäjilla ja pahoittelut mahdollisista ongelmista.

Päivitys: Näyttäisi siltä että mahdollinen vuoto koski vanhaa phpBB2 tietokantaa,
joten helmikuuta 2012 uudemmat tiedot pitäisi olla turvassa.

-Lahha
yllapito@elektroniikkafoorumi.com


ATmega ADC-kanavien lukuongelma

Keskustelua mikrokontrollereista ja niiden ohjelmoinnista.

Valvoja: Moderaattorit


Jäsen
Jäsen
Viestit: 115
Liittynyt: Su Heinä 08, 2007 21:05
ViestiLähetetty: Ke Kesä 12, 2013 15:11
Yritän lukea ADC-kanavista 0..2 oheisella koodilla lukemia, mutta pientä ongelmaa tuntuu olevan. Kanavat 1 ja 2 näyttäisivät toimivan aika hyvin, mutta 0 kanava muuttuu myös samaan aikaan, kun säätää kanavaa 2. Omasta potikastaan (Kanava 0) se ei tosin muutu ollenkaan.

Elektroniikan olen tarkistanut moneen kertaan, etteivät ole yhdessä.

Tämän hetken epäilys on tuossa ADC:n lukufunktiossa, että se ryssiin arvojen luvun/tallennuksen jotenkin, mitä en nyt keksi. Olisiko ideoita? Kaikki lukemat ovat siististi 0...1023 välissä eikä ne hypi mitenkään epämääräisesti.

Koodi: Valitse kaikki
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <util/delay.h>

#define F_CPU 8000000UL  // 8 MHz
#define BAUDRATE 9600 // sarjaportin nopeus 9600 bps
#define MYUBRR ((F_CPU / (BAUDRATE * 16UL) - 1)

// prototypes
void USART_Transmit(uint8_t data);
void USART_Init(unsigned int ubrr);
void USART_send( unsigned char data);   //Function that sends a char over the serial port
void USART_putstring(char* StringPtr);  //Function that sends a string over the serial port

#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))

uint16_t read_adc(uint8_t channel);      //Function to read an arbitrary analogic channel/pin

//Variables
uint16_t adc_value;                  //Variable used to store the value read from the ADC
uint16_t adc_store[6];               //Stored adc value
char buffer[10];                  //Output of the itoa function
uint8_t i=0;                     //Variable for the for() loop

//USART eli sarjaportin asetukset, 8 data, 1 stop bit, 8N1
void init_USART(void)
{
   // Set baud rate, lasketaan bittien siirtonopeus
   UBRR0H = 0x00; // write high register first
   UBRR0L = ((F_CPU/16)/BAUDRATE)-1;
   UCSR0B |= (1<<RXEN0)|(1<<TXEN0); // 0001 1000
   UCSR0B |= 1<<RXCIE0; // rx interrupt enable, 1xx1 1xxx
   // sarjavastaanottokeskeytys sallittu
   // UCSR0C = 0x86; // 8 Data, 1 Stop, No Parity 1xxx x11x
   UCSR0C |= (1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);
}

void init_outputs(void){
   //Määritetään Portin D pinnit 6 ja 7 lähdöiksi
   DDRD |= (1<<PD6) | (1<<PD7);
   //Määritetään alkutila nollaksi
   PORTD =0x00;
   
   //Määritetään Portin B pinnit 0,1 ja 2 lähdöiksi
   DDRB |= (1<<PD0) | (1<<PD1) | (1<<PD2);   
   //Määritetään alkutila nollaksi
   PORTD = 0x00;
}

void init_ADC(void){
   ADCSRA |= ((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));   //16Mhz/128 = 125Khz the ADC reference clock
   ADMUX |= (1<<REFS0);                         //Voltage reference from Avcc (5v)
   ADCSRA |= (1<<ADEN);                         //Turn on ADC
   ADCSRA |= (1<<ADSC);                     //Do an initial conversion
   while(ADCSRA & (1<<ADSC));                  //Wait until the conversion is done
   return ADCW;
}

uint16_t read_adc(uint8_t channel){
   ADMUX &= 0xF8;                  //Clear the older channel that was read
   ADMUX |= channel;                   //Defines the new ADC channel to be read
   _delay_ms(1);
   ADCSRA |= (1<<ADSC);               //Starts a new conversion
   while(ADCSRA & (1<<ADSC));         //Wait until the conversion is done
   // Clear conversion completed flag
   ADCSRA |= 0x10;
   return ADCW;                      //Returns the ADC value of the chosen channel
}

int main(void)
{
   //Initialization
   init_USART();
   init_ADC();
   init_outputs();
   
   //Enable delay for 10 seconds
   for(i=0; i<5; i++){
      // Blink PWR led
      SETBIT(PORTB,2); //PWR
      _delay_ms(500);   
      CLEARBIT(PORTB,2); //PWR
      _delay_ms(500);
   }
   
   sei(); // global interrut ON
   
   //Main program loop
   while(1)
   {
      for(i=0; i<4; i++){ //Luetaan adc-kanavat
 
          USART_putstring("Reading channel ");
          USART_send('0' + i);               
          USART_putstring(" : ");            //Just to keep things pretty
          adc_value = read_adc(i);           //Read one ADC channel
         adc_store[i] = adc_value;         //Move ADC-value to buffer
          itoa(adc_value, buffer, 10);      //Convert the read value to an ascii string
          USART_putstring(buffer);           //Send the converted value to the terminal
          USART_putstring("  ");               //Some more formatting
       }
       _delay_ms(1000); 
       USART_send(0x1B); //ESC
      USART_send(0x5B); //[
      USART_send(0x32); //2
      USART_send(0x4A); //J
       USART_send(0x1B);  //Esc                
      USART_send(0x5B); //[
      USART_send(0x48); //H
      
      //Päivitetään lähdöt
      //Set enable ON
      SETBIT(PORTB,2); //PWR
      
      //Half On Full OFF
      if ((adc_store[2] > adc_store[0]) & (adc_store[1] < adc_store[0]))
      {
         //Half power on
         SETBIT(PORTB,0); //Half
         //Full power OFF
         CLEARBIT(PORTB,1); //Full
         
         //Half On AND Full ON
         if((adc_store[2] > adc_store[0]) & (adc_store[1] > adc_store[0]))
         {
            SETBIT(PORTB,0); //Half
            //Full power OFF
            SETBIT(PORTB,1); //Full      
         }
      }       
      else
      {
         //Half power OFF
         CLEARBIT(PORTB,0); //Half
         //Full power OFF
         CLEARBIT(PORTB,1); //Full
      }

   }
return 0;
}

void USART_send( unsigned char data){

   while(!(UCSR0A & (1<<UDRE0)));
   UDR0 = data;

}

void USART_putstring(char* StringPtr){

   while(*StringPtr != 0x00){
      USART_send(*StringPtr);
   StringPtr++;}

}
"Now we're all sons of bitches." - Kenneth Bainbridge

Jäsen
Jäsen
Viestit: 148
Liittynyt: Pe Marras 18, 2011 8:19
ViestiLähetetty: Ke Kesä 12, 2013 15:55
Aina kun vaihdat ADC-kanavaa niin ensimmäinen muunnos voi olla mitä sattuu. Lue kaksi muunnosta ja valitse arvoksi jälkimmäinen.

Kokelas
Kokelas
Viestit: 7
Liittynyt: Ma Maalis 15, 2010 23:15
ViestiLähetetty: Pe Kesä 21, 2013 16:03
Mittaa suoraan Controllerin pinnistä (kanava 0), mitä jännitemittari näyttää ja totteleeko potikkaa.

Jäsen
Jäsen
Viestit: 115
Liittynyt: Su Heinä 08, 2007 21:05
ViestiLähetetty: Ma Kesä 24, 2013 12:08
No se nyt oli ensimmäinen toimenpide, kun ongelmia ilmeni. Ohjelman suuntaan ongelmat viittaavat edelleen.
"Now we're all sons of bitches." - Kenneth Bainbridge

Jäsen
Jäsen
Viestit: 148
Liittynyt: Pe Marras 18, 2011 8:19
ViestiLähetetty: Ma Kesä 24, 2013 18:46
Kokeilitko jo tehdä kaksi muunnosta peräjälkeen kanavan vaihdon jälkeen. Se on ihan speksattu ongelma.
When switching to a differential gain channel, the first conversion result may have a poor accuracy
due to the required settling time for the automatic offset cancellation circuitry. The user
should preferably disregard the first conversion result.


Eli muunnos kaksi kertaa peräkkäin.

Koodi: Valitse kaikki
uint16_t read_adc(uint8_t channel){
   ADMUX &= 0xF8;                  //Clear the older channel that was read
   ADMUX |= channel;                   //Defines the new ADC channel to be read
   _delay_ms(1);
   ADCSRA |= (1<<ADSC);               //Starts a new conversion
   while(ADCSRA & (1<<ADSC));         //Wait until the conversion is done
   ADCSRA |= (1<<ADSC);               //Starts a new conversion
   while(ADCSRA & (1<<ADSC));         //Wait until the conversion is done
   // Clear conversion completed flag
   ADCSRA |= 0x10;
   return ADCW;                      //Returns the ADC value of the chosen channel
}

Jäsen
Jäsen
Viestit: 115
Liittynyt: Su Heinä 08, 2007 21:05
ViestiLähetetty: Ma Kesä 24, 2013 19:54
Joo, kokeilin. Ei auttanut. Kokeilin myös lukea ainoastaan ekaa kanavaa (0), eikä sekään toimi. Täytyy vissiin kaivaa ATMega328 proto-kortti esille, jossa koodeja aikaisemmin testailin.
"Now we're all sons of bitches." - Kenneth Bainbridge

Jäsen
Jäsen
Viestit: 115
Liittynyt: Su Heinä 08, 2007 21:05
ViestiLähetetty: To Syys 12, 2013 15:30
Asetuksissa / lukuajurissa se vika olikin, kuten epäilinkin. ADMUX-asetukset meni persiilleen heti ensimmäisellä luku yrityksellä.
"Now we're all sons of bitches." - Kenneth Bainbridge

Kokelas
Kokelas
Viestit: 7
Liittynyt: Ma Maalis 15, 2010 23:15
ViestiLähetetty: Pe Syys 20, 2013 18:16
Missä kohtaa tuota koodiasi se tarkalleen oli se ongelma ?

"Asetuksissa / lukuajurissa se vika olikin, kuten epäilinkin. ADMUX-asetukset meni persiilleen heti ensimmäisellä luku yrityksellä."

Jäsen
Jäsen
Viestit: 115
Liittynyt: Su Heinä 08, 2007 21:05
ViestiLähetetty: La Syys 21, 2013 10:24
ADMUX REFS0 ja REFS1 asetukset jyrättiin lukufunktiossa 0x40 --> 0xF8.
"Now we're all sons of bitches." - Kenneth Bainbridge

Paluu Mikrokontrollerit ja ohjelmointi

Paikallaolijat

Käyttäjiä lukemassa tätä aluetta: Ei rekisteröityneitä käyttäjiä ja 1 vierailijaa

cron