Maker Pro
Maker Pro

Can't implement microcontroller in Proteus

robi10101298

May 25, 2020
21
Joined
May 25, 2020
Messages
21
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
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,719
Joined
Nov 17, 2011
Messages
13,719
Are the wires connected OK? If not, why?
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.

What am I doing wrong?
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).
 

robi10101298

May 25, 2020
21
Joined
May 25, 2020
Messages
21
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).
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);

      }
}
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,719
Joined
Nov 17, 2011
Messages
13,719
I do not understand this part:
// ADC Voltage Reference: 1.1V, cap. on AREF
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?
temperature=res*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.
 

robi10101298

May 25, 2020
21
Joined
May 25, 2020
Messages
21
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.
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
 

robi10101298

May 25, 2020
21
Joined
May 25, 2020
Messages
21
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.
Where this res*453 comes from?
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,719
Joined
Nov 17, 2011
Messages
13,719
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

May 25, 2020
21
Joined
May 25, 2020
Messages
21
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?
It was a calculation mistake, I was going to say that your answer it's correct
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,719
Joined
Nov 17, 2011
Messages
13,719
Where this res*453 comes from?
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.
 
Top