YADU SHARON
BACK


Input Devices


The assignment for this week is to "measure something: add a sensor to a microcontroller board that you have designed and read it". My plan is to make something which will be also useful for my final project. So I decided to interface a dual axis joystick using the ADC interface of micro controller. Simply a joystick consists of two potentio meters. When we move the knob of joystick the potentio meter gives different analog voltage according to the position of the knob. So measuring the analog voltage from the two pots we can determine four (or more) conditions from the joystick.


The Joystick has five pins, which are

  • VCC
  • Ground
  • A1 - Analog value 1
  • A2 - Analog value 2
  • S - A central digital switch

  • When we move the knob in X and Y axes the analog value in A1 and A2 varies. Measuring this value we can determine the position of the joystick knob.

    Design

    I am planning to design a board which can be used for my project also. SO it hase some pins for joystick and someher pins also for serial communication , stepper motor controlling etc. Anyway the chip i am going to use is atmega 328p.



    I milled the board in modella and soldered the components


    Programming The atmega 328 has ADC with 10bit resolution which means , if we are connecting 5V as reference voltage then the chip can measure the difference of 5/1024 V.
    The registers related to ADC are
  • ADMUX – ADC Multiplexer Selection Register
  • ADCSRA – ADC Control and Status Register A
  • ADCL and ADCH – The ADC Data Register
  • ADCSRB – ADC Control and Status Register B


  • Lets go deeper. The first step is to initialize the ADC. So for that we have to decide which is our reference voltage. If we have an external voltage as reference we can choose that, or we can connect the Vref to internal reference voltage. REFS1 and REFS0 in ADMUX is used to select that.

    In my case i have a VREF externally connected with capacitor, so i choose that. So i have to write a 1 to REFS0.
        
        ADMUX |= (1<< REFS0);
        
        
    To set which channel is using for ADC, we have four bits in the ADMUX register which are MUX3-0.



    So if we are using the ADC0 pin (atmega 328p PC0 ) nothing to write to MUX3-0 because by default those values will be zero. But if we want to use ADC1 then we have to write 1 to MUX1.

    Next we go to the ADCSRA register. Here we have the ADEN pin which enables the ADC. If we write 1 to ADEN then ADC is turned on. If we write 0, the ADC is turned off.
    Next thing is to select the clock prescaler. The prescaler divide the clock by a factor for the ADC. We have 7 different prescale factors which can be selected by ADPS2-0 bits in ADCSRA register.



    I dont know the difference between the prescalers in real , but i used to choose the prescaler as 128.
    So for this register the total change we need to make is :
    
        ADCSRA |= (1<< ADPS2)|(1<< ADPS1)|(1<< ADPS0)|(1<< ADEN);
    
        
    To start the ADC conversion we there is a bit ADSC in ADCSRA register. When it is written 1 the ADC will start. So final code for reading an Analog value will be

    
        #include <avr/io.h>
        #define F_CPU 8000000
        #include <util/delay.h>
    
        void InitADC(){
    
            ADMUX |= (1<< REFS0);
    
            ADCSRA |= (1<< ADPS2)|(1<< ADPS1)|(1<< ADPS0)|(1<< ADEN);
        }
    
        uint16_t ReadADC(uint8_t ADCchannel){           // in order to use any channel
    
            ADMUX = (ADMUX & 0xF0) | (ADCchannel & 0x0F);
    
            ADCSRA |= (1<< ADSC);
    
            while( ADCSRA & (1<< ADSC) );
            return ADC;
        }
    
        int main(){
    
        int adc0, adc1;
        InitADC();
    
    
            while(1){
    
    
                adc0 = ReadADC(0);      // read the adc valuein channel 0
                adc1 =  ReadADC(1);     // Read the adc value in channel 1
    
    
            }
    
    
        }
    
    
        


    The connections are made like:

  • VCC to Board 5V
  • Ground to board ground
  • Analog pin 1 to atmega 328 ADC0 (PC0)
  • Analog pin 2 to Atmega 328 ADC1 (PC1)



  • I have written the code in C which will read the ADC value and send some values via UART. The chip is connected to PC via FTDI connector. I have written a simple python program for animating a circle using the joystick. The circle will move left and right when we move the joystick.



    Here is the C Code for the Atmega328p. Here is the Python code which run in the PC