Connect with us

Can't implement microcontroller in Proteus

Discussion in 'Microcontrollers, Programming and IoT' started by robi10101298, Nov 26, 2020.

Scroll to continue with content
  1. robi10101298

    robi10101298

    21
    0
    May 25, 2020
    Hello guys,
    I'm trying to build a graphic display thermometer in Proteus, with an LM35 sensor using the ATmega 164 microcontroller.

    My problem is that I don't know how to connect the temperature sensor to the microcontroller.

    • What am I doing wrong?
    • Are the wires connected OK? If not, why?
    upload_2020-11-26_16-28-24.png
     
  2. Harald Kapp

    Harald Kapp Moderator Moderator

    11,276
    2,583
    Nov 17, 2011
    Assuming pin 1 of the LM35 and pin 4 of the Atmega are connected to +5 V, the wiring of the sensor is o.k.

    To answer this we need to know:
    • What is the expected behavior?
    • What is the error you observe?
    • Have you verified that the LCD is controlled correctly (e.g. by having it show some dummy values)?
    Show us your code (use the Insert... -> Code box in the menu bar).
     
  3. robi10101298

    robi10101298

    21
    0
    May 25, 2020
    Here its my code that was done using the CodeVisionAVR and my final schematic. As you can see, instead of 26 degrees I have 26.9, so I think it's only a calculation thing:
    upload_2020-11-27_10-9-59.png
    Code:
    #include <mega164a.h>
    #include <stdio.h>
    #include <delay.h>
    
    // Alphanumeric LCD functions
    #include <alcd.h>
    
    // Declare your global variables here
    
    // Voltage Reference: 1.1V, cap. on AREF
    #define ADC_VREF_TYPE ((1<<REFS1) | (0<<REFS0) | (1<<ADLAR))
     int res = 0;
     float temperature=0.0;
    // Read the 8 most significant bits
    // of the AD conversion result
    unsigned char read_adc(unsigned char adc_input)
    {
    ADMUX=adc_input | ADC_VREF_TYPE;
    // Delay needed for the stabilization of the ADC input voltage
    delay_us(10);
    // Start the AD conversion
    ADCSRA|=(1<<ADSC);
    // Wait for the AD conversion to complete
    while ((ADCSRA & (1<<ADIF))==0);
    ADCSRA|=(1<<ADIF);
    return ADCH;
    }
        unsigned char buffer[16];
    void main(void)
    {
    // Declare your local variables here
    
    // Crystal Oscillator division factor: 1
    #pragma optsize-
    CLKPR=(1<<CLKPCE);
    CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
    #ifdef _OPTIMIZE_SIZE_
    #pragma optsize+
    #endif
    
    // Input/Output Ports initialization
    // Port A initialization
    // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
    DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0);
    // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
    PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);
    
    // Port B initialization
    // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
    DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
    // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
    PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
    
    // Port C initialization
    // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
    DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
    // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
    PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);
    
    // Port D initialization
    // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
    DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
    // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
    PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
    
    // Timer/Counter 0 initialization
    // Clock source: System Clock
    // Clock value: Timer 0 Stopped
    // Mode: Normal top=0xFF
    // OC0A output: Disconnected
    // OC0B output: Disconnected
    TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
    TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (0<<CS00);
    TCNT0=0x00;
    OCR0A=0x00;
    OCR0B=0x00;
    
    // Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: Timer1 Stopped
    // Mode: Normal top=0xFFFF
    // OC1A output: Disconnected
    // OC1B output: Disconnected
    // Noise Canceler: Off
    // Input Capture on Falling Edge
    // Timer1 Overflow Interrupt: Off
    // Input Capture Interrupt: Off
    // Compare A Match Interrupt: Off
    // Compare B Match Interrupt: Off
    TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
    TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
    TCNT1H=0x00;
    TCNT1L=0x00;
    ICR1H=0x00;
    ICR1L=0x00;
    OCR1AH=0x00;
    OCR1AL=0x00;
    OCR1BH=0x00;
    OCR1BL=0x00;
    
    // Timer/Counter 2 initialization
    // Clock source: System Clock
    // Clock value: Timer2 Stopped
    // Mode: Normal top=0xFF
    // OC2A output: Disconnected
    // OC2B output: Disconnected
    ASSR=(0<<EXCLK) | (0<<AS2);
    TCCR2A=(0<<COM2A1) | (0<<COM2A0) | (0<<COM2B1) | (0<<COM2B0) | (0<<WGM21) | (0<<WGM20);
    TCCR2B=(0<<WGM22) | (0<<CS22) | (0<<CS21) | (0<<CS20);
    TCNT2=0x00;
    OCR2A=0x00;
    OCR2B=0x00;
    
    // Timer/Counter 0 Interrupt(s) initialization
    TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (0<<TOIE0);
    
    // Timer/Counter 1 Interrupt(s) initialization
    TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (0<<TOIE1);
    
    // Timer/Counter 2 Interrupt(s) initialization
    TIMSK2=(0<<OCIE2B) | (0<<OCIE2A) | (0<<TOIE2);
    
    // External Interrupt(s) initialization
    // INT0: Off
    // INT1: Off
    // INT2: Off
    // Interrupt on any change on pins PCINT0-7: Off
    // Interrupt on any change on pins PCINT8-15: Off
    // Interrupt on any change on pins PCINT16-23: Off
    // Interrupt on any change on pins PCINT24-31: Off
    EICRA=(0<<ISC21) | (0<<ISC20) | (0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
    EIMSK=(0<<INT2) | (0<<INT1) | (0<<INT0);
    PCICR=(0<<PCIE3) | (0<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);
    
    // USART0 initialization
    // USART0 disabled
    UCSR0B=(0<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (0<<RXEN0) | (0<<TXEN0) | (0<<UCSZ02) | (0<<RXB80) | (0<<TXB80);
    
    // USART1 initialization
    // USART1 disabled
    UCSR1B=(0<<RXCIE1) | (0<<TXCIE1) | (0<<UDRIE1) | (0<<RXEN1) | (0<<TXEN1) | (0<<UCSZ12) | (0<<RXB81) | (0<<TXB81);
    
    // Analog Comparator initialization
    // Analog Comparator: Off
    // The Analog Comparator's positive input is
    // connected to the AIN0 pin
    // The Analog Comparator's negative input is
    // connected to the AIN1 pin
    ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
    // Digital input buffer on AIN0: On
    // Digital input buffer on AIN1: On
    DIDR1=(0<<AIN0D) | (0<<AIN1D);
    
    // ADC initialization
    // ADC Clock frequency: 625.000 kHz
    // ADC Voltage Reference: 1.1V, cap. on AREF
    // ADC Auto Trigger Source: Free Running
    // Only the 8 most significant bits of
    // the AD conversion result are used
    // Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
    // ADC4: On, ADC5: On, ADC6: On, ADC7: On
    DIDR0=(0<<ADC7D) | (0<<ADC6D) | (0<<ADC5D) | (0<<ADC4D) | (0<<ADC3D) | (0<<ADC2D) | (0<<ADC1D) | (0<<ADC0D);
    ADMUX=ADC_VREF_TYPE;
    ADCSRA=(1<<ADEN) | (0<<ADSC) | (1<<ADATE) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);
    ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
    
    // SPI initialization
    // SPI disabled
    SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);
    
    // TWI initialization
    // TWI disabled
    TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);
    
    // Alphanumeric LCD initialization
    // Connections are specified in the
    // Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
    // RS - PORTC Bit 0
    // RD - PORTC Bit 1
    // EN - PORTC Bit 2
    // D4 - PORTC Bit 4
    // D5 - PORTC Bit 5
    // D6 - PORTC Bit 6
    // D7 - PORTC Bit 7
    // Characters/line: 20
    lcd_init(20);
     
     
    
    while (1)
          {
          // Place your code here
          lcd_clear();
          res=read_adc(0);
          temperature=res*0.442;
          sprintf(buffer, "%f", temperature);
         
          lcd_puts(buffer);
          delay_ms(1500);
    
          }
    }
    
     
  4. Harald Kapp

    Harald Kapp Moderator Moderator

    11,276
    2,583
    Nov 17, 2011
    I do not understand this part:
    There is no external 1.1 V reference connected to AREF. Internal reference would be 2.5 V or Vcc (5 V).

    Ho do you arrive at this factor 0.442?
    By the way, doing float arithmetic on a microcontroller without floating point unit is very slow.
    Try using (long) integer arithmetic like
    Code:
    temperature= (res*442)/1000
    Division still takes a lot of time. By modifying the equation like this: 442 / 1000 = 453 / 1024 (approx.), and noting that 1024 = 210 and also noting that a division by 210 is equivalent to shifting the divisor 10 places to the right you get this code:
    Code:
    temperature = (res*453)>>10
    Note: these are mere suggestions to speed up the code which is not really necessary here but may come in handy once your code grows larger and slower.
     
  5. robi10101298

    robi10101298

    21
    0
    May 25, 2020
    I've just connected a 1.1 external reference to AREF upload_2020-11-27_10-53-20.png
    Your code it's correct, thanks <3
    upload_2020-11-27_10-55-37.png
     
  6. robi10101298

    robi10101298

    21
    0
    May 25, 2020
    Where this res*453 comes from?
     
  7. Harald Kapp

    Harald Kapp Moderator Moderator

    11,276
    2,583
    Nov 17, 2011
    The ADC is a 10 bit type. With Vref = 1.1 V this is equivalent to a conversion factor cf = 4095 bit / 1.1 V.
    From the LM35 you get an scale factor of sfLM35 = 10 mV / 1 °C
    Combining these you get temperature = reading / (cf × sf) = reading / 37.2 = reading × 0.0269
    Check: 25 °C -> 250 mV -> reading = (0.25 V / 1.1. V) × 4095 = 930 -> temperature = 930 / 37,2 = 25 °C
    So where does your factor 0.442 come from?
     
    robi10101298 likes this.
  8. robi10101298

    robi10101298

    21
    0
    May 25, 2020
    It was a calculation mistake, I was going to say that your answer it's correct
     
  9. Harald Kapp

    Harald Kapp Moderator Moderator

    11,276
    2,583
    Nov 17, 2011
    You want to compute 422/1000 (to use integers only instead of 0.442)
    Since division by 1000 is comparatively complex but division by 1024 is really easy, you need to ransform the above equation:
    453 = 442 * 1024/1000

    453/1024 = 422/1000 (apart from rounding errors)

    But 422 or 453, I think, as shown above, the factor is incorrect.
     
    robi10101298 likes this.
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-