help to do a project with an atmega328pb and max665 thermocouple sensor interacting with an lcd display
Atmega328pb
Step one is to be able to program the 328PB controller
without attaching anything to it, other than perhaps an
LED (with a current-limiting resistor). Once you can
load code and blink the LED, you are well on your way.
Step two could be learning to write to the display. There
are already-written libraries available for common displays
so you might want to search for these instead of writing
your own code from scratch. Otherwise, search for the
datasheet of the display to find out how to write to it.
Step three is to learn to read data from the sensor. Again
there are probably libraries you can just use for this if you
aren't trying to write the code yourself. You'll need to know
what protocol the sensor uses. Maybe it's SPI or I2C (TWI).
The sensor's datasheet will tell you.
Step four is to combine everything into one project where
you read from the sensor and then output the values to
the display.
If you get stuck during any of these steps you can ask
specific questions showing schematics and code and some
one here can likely help.
--Mike
Have you taken a look at any of the many AVR tutorials on this and other sites? Try going through a few of them to get ideas for creating your project code.
max665 thermocouple sensor
Are you sure that is the correct part number? Details are important.
Jim
When I tried searching earlier I hit some threads back at Freaks about a "6675". Wonder if it's really that (in which case those threads would be relevant reading too).
it was my mistake it is a max6665 thermocouple sensor, I have to interface with an lcd keypad shield through SPI, using the ATmega328pb microcontroller. I write the following code, but I am not getting in the display the reading from the thermocouple, can someone please help me
Code:
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#define MOSI 3
#define SCK 5
#define SS 2
#define LCD_DPRT PORTD
#define LCD_DDDR DDRD
#define LCD_DPIN PIND
#define LCD_CPRT PORTB
#define LCD_CDDR DDRB
#define LCD_CPIN PINB
#define LCD_RS 0
#define LCD_RW 4
#define LCD_EN 1
void lcdComrnand( unsigned char cmnd )
{
LCD_DPRT = cmnd & 0xF0;
LCD_CPRT &= ~(1<<LCD_RS);
LCD_CPRT &= ~ (1<<LCD_RW);
LCD_CPRT |= (1<<LCD_EN);
_delay_ms(1);
LCD_CPRT &= ~(1<<LCD_EN);
_delay_ms(100);
LCD_DPRT = cmnd<<4;
LCD_CPRT |= (1<<LCD_EN);
_delay_ms(1);
LCD_CPRT &= ~(1<<LCD_EN);
_delay_ms(100);
}
void lcdData( unsigned char data )
{
LCD_DPRT = data & 0xF0;
LCD_CPRT |= (1<<LCD_RS);
LCD_CPRT |= (1<<LCD_EN);
_delay_ms(1);
LCD_CPRT &= ~(1<<LCD_EN);
LCD_DPRT = (LCD_DPRT & 0x0F) | (data<<4);
LCD_CPRT |= (1<<LCD_EN);
_delay_ms(1);
LCD_CPRT &= ~(1<<LCD_EN);
_delay_ms(100);
}
void lcd_init()
{
LCD_DDDR = 0xFF;
LCD_CDDR = 0x03;
LCD_CPRT &=~(1<<LCD_EN);
lcdComrnand(0x33);
lcdComrnand(0x32);
lcdComrnand(0x28);
lcdComrnand(0x0E);
lcdComrnand(0x01);
_delay_ms(2000);
lcdComrnand(0x06);
}
void lcd_gotoxy(unsigned char x, unsigned char y)
{
unsigned char firstCharAdr[] ={0x81, 0xC0, };
lcdComrnand(firstCharAdr[ y-1] + x - 1);
_delay_ms(100);
}
void lcd_print( char *str )
{
unsigned char i = 0;
while (str[ i] !=0)
{
lcdData (str[ i] ) ;
i++ ;
}
}
void dataRead( unsigned int )
{
unsigned int j = SPDR0;
j<<8;
j|=SPDR0;
}
//**************************************************************************
int main()
{
DDRB = (1<<MOSI)|(1<<SCK)|(1<<SS);
DDRD = 0xFF;
SPCR0 = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
PORTB &=~(1<<SS);
SPDR0 = 'j';
while(!(SPSR0 &(1<<SPIF)));
PORTD = SPDR0;
PORTB |= (1<<SS);
lcd_init();
lcd_gotoxy(1,1);
lcd_print("%d, j");
while(1);
return 0;
}
did you manage to put "hello world" on the display?
and you do know that ms = miliseconds and not micro seconds right?
there are a number of delays in your write routines that are massive, wonder if they are needed and if you not have taken the wrong delay time.
in combination with a wrong clock speed that might be visually killing.
you have set the fuses to match the selected clock input?
for instance you state you have a 16mHz clock source somewhere. but if you actually run at internal RC with default fuses times are 16x longer, so a 100ms delay will become 1,6 seconds a 2 second delay will become 32.........
And for the impatient programmer expecting things to happen with the blink of an eye that is a massive "help my thingy does not work"
void dataRead( unsigned int ) { unsigned int j = SPDR0; j<<8; j|=SPDR0; }
Umm I don't think so for many reasons.
Presumably this was supposed to look something like:
uint8_t SPI_transfer(uint8_t byte) { SPDR = byte; while(!(SPSR0 & (1 << SPIF))); return SPDR; } uint16_t dataRead(void) { uint16_t j; j = SPI_transfer(0xFF) << 8; j |= SPI_transfer(0xFF); }
Of course, for this to be useful you then have to call it somewhere. At present all you have is:
lcd_print("%d, j");
which appears to be printing some variable called 'j' and yet I don't see where that is either defined or assigned? (it will have nothing to do with the local 'j' in your uncalled dataRead( ) function.
BTW in the above I have introduced an SPI_transfer() function - this recognizes the fact that every time you use SPI you both send and receive a byte. Sometimes the value of the byte you send does not matter but, as master, you still have to send it to make the SPI system "clock". In the example code I am sending a dummy 0xFF value each time simply to persuade the device to actually return the high and low bytes I'm interested in. (does it really return high then low rather than low then high??).
Just this small bit of your code I have looked at suggests to me that you don't yet have a grasp of even the fundamentals of C programming (like returning values from functions) so I would spend a few weeks just learning C basics before trying to apply that to an actual AVR application.
PS even this:
void lcd_print( char *str ) { unsigned char i = 0; while (str[ i] !=0) { lcdData (str[ i] ) ; i++ ; } }
could be better - there's no need for 'i' in this:
void lcd_print( char *str ) { while (*str) { lcdData (*str++) ; } }
EDIT: actually I just noticed another thing. Your program structure is essentially:
int main() { lcd_init(); lcd_print("%d, j"); while(1); }
Surely you don't want it to just make one reading at power on then stop? Surely you want a structure more like:
int main() { uint16_t j; lcd_init(); while(1) { j = dataRead(); lcd_print("%d, j"); } }
so that it attempts to read and print over and over again.
(obviously I left out a whole bunch of other init stuff - you need that back as well).
Oh hold on. I just realised you used:
lcd_print("%d, j");
My eyesight must be failing - even THAT is wrong. If this lcd_print() function is something like printf() with variadic parameters then I imagine you mean:
lcd_print("%d", j);
but if it isn't then you need to convert the value into a string first using a function such as sprintf():
char buf[30]; ... sprintf(buf, "%d", j); lcd_print(buf);
As I say there are just so many fundamental C errors in the code that I think you need to take a step back and learn C first before trying to do anything with it like reading thermocouples.
After work very hard to fix my code to get my project done, I did some improvement to my code, but I am not getting the temperature on the display still. Any ideas what am I missing on this code.
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#define LCD_DPRT PORTD
#define LCD_DDDR DDRD
#define LCD_DPIN PIND
#define LCD_CPRT PORTB
#define LCD_CDDR DDRB
#define LCD_CPIN PINB
#define LCD_RS 0
#define LCD_RW 2
#define LCD_EN 1
#define MOSI 3
#define MISO 4
#define SCK 5
#define SS 2
void lcdComrnand( unsigned char cmnd )
{
LCD_DPRT = (LCD_DPRT & 0x0F)|(cmnd & 0xF0);
LCD_CPRT &= ~(1<<LCD_RS);
LCD_CPRT &= ~ (1<<LCD_RW);
LCD_CPRT |= (1<<LCD_EN);
_delay_ms(1);
LCD_CPRT &= ~(1<<LCD_EN);
_delay_ms(100);
LCD_DPRT = (LCD_DPRT & 0x0F)|cmnd<<4;
LCD_CPRT |= (1<<LCD_EN);
_delay_ms(1);
LCD_CPRT &= ~(1<<LCD_EN);
_delay_ms(100);
}
void lcdData( unsigned char data )
{
LCD_DPRT = data & 0xF0;
LCD_CPRT |= (1<<LCD_RS);
LCD_CPRT |= (1<<LCD_EN);
_delay_ms(1);
LCD_CPRT &= ~(1<<LCD_EN);
LCD_DPRT = (LCD_DPRT & 0x0F) | (data<<4);
LCD_CPRT |= (1<<LCD_EN);
_delay_ms(1);
LCD_CPRT &= ~(1<<LCD_EN);
_delay_ms(100);
}
void lcd_init()
{
LCD_DDDR = 0xF0;
LCD_CDDR = 0x03;
LCD_CPRT &=~(1<<LCD_EN);
lcdComrnand(0x33);
lcdComrnand(0x32);
lcdComrnand(0x28);
lcdComrnand(0x0E);
lcdComrnand(0x01);
_delay_ms(2000);
lcdComrnand(0x06);
}
void lcd_gotoxy(unsigned char x, unsigned char y)
{
unsigned char firstCharAdr[] ={0x81, 0xC0, 0x94, 0xD4};
lcdComrnand(firstCharAdr[ y-1] + x - 1);
_delay_ms(100);
}
void lcd_print( char *str )
{
unsigned char i = 0;
while (str[ i] !=0)
{
lcdData (str[ i] ) ;
i++ ;
}
}
char dataWrite(char cData)
{
DDRB = (1<<MOSI)|(1<<SCK)|(1<<SS);
DDRB = ~(1<<MISO);
SPCR0 = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<CPHA)|(1<<CPOL);
PORTB &=~(1<<SS);
SPDR0 = cData;
SPDR0 = cData << 8;
SPDR0 |= SPDR0;
while(!(SPSR0 & (1<<SPIF)));
PORTD = SPDR0;
PORTB |= (1<<SS);
}
//**************************************************************************
int main()
{
lcd_init();
lcd_gotoxy(1,1);
lcd_print("Temperature");
lcd_gotoxy(1,2);
lcd_print(dataWrite(PORTD));
while(1);
return 0;
}
After work very hard to fix my code to get my project done, I did some improvement to my code,
The description you provide is very lacking...does the display work AT ALL? Can you get it to say "hello" ...why do you overlook stating what is working?
We can not tell what is happening...you could even have bad wiring. Getting the display functioning is step one, before trying to show other items that themselves need to be up & running.
The display is working, I print hello, and did others test to see if the code for the display is right, and it seems to work perfectly, after that I attached a max6675 thermocouple and add the code to get the temperature and print it in the display, but I am not able to do it.
Ok, that is good to know (you should state this earlier!)--so now we can concentrate on whether the readings are simply not coming in, or whether reading are being rcvd, but not being formatted properly such that they will show on the display
Your code makes little sense. At one stage you use lcd_print("Temperature") which suggests the function takes char * and yet later you call lcd_print() but passing a parameter of dataWrite() which is a function that has a char not char * return and what's more the function itself does not even contain a return statement anyway?
Suggest you stop to think about the design of this before rushing to implementation.