// --------------------------------------------------------------------------- // Created by Francisco Malpartida on 1/1/12. // Copyright 2011 - Under creative commons license: // Attribution-NonCommercial-ShareAlike CC BY-NC-SA // // This software is furnished "as is", without technical support, and with no // warranty, express or implied, as to its usefulness for any purpose. // // Thread Safe: No // Extendable: Yes // // @file i2CLCDextraIO.pde // Temperature logging to demonstrate the I2CLCDextraIO library. // // @brief This application is a demostration file for the I2CLCDextraIO library // that reads a temperature from the internal ATMEGA328p temperature sensor // and displays it on the LCD. The application also demonstrates some of the // methods of the library, such as loading custom characters to the LCD, // moving around the LCD, and writing to it. // // @author F. Malpartida // --------------------------------------------------------------------------- #include #include #define _LCD_I2C_ #ifdef _LCD_I2C_ #include #endif #ifdef _LCD_4BIT_ #include #endif /*! @defined CHAR_WIDTH @abstract Character witdth of the display, expressed in pixeles per character. */ #define CHAR_WIDTH 5 /*! @defined BACKLIGHT_PIN @abstract LCD backlight pin definition. @discussion AVR pin used for the backlight illumintation of the LCD. */ #define BACKLIGHT_PIN 7 /*! @defined TEMP_CAL_OFFSET @abstract Temperature calibration offset. @discussion This is the offset value that has to be modified to get a correct temperature reading from the internal temperature sensor of your AVR. */ #define TEMP_CAL_OFFSET 334 /*! @defined FILTER_ALP @abstract Low pass filter alpha value @discussion This value defines how much does the current reading, influences the over all value. The smaller, the less influence the current reading has over the overall result. */ #define FILTER_ALP 0.1 extern unsigned int __bss_end; extern unsigned int __heap_start; extern void *__brkval; #ifdef _LCD_I2C_ LiquidCrystal_I2C lcd(0x38); // set the LCD address to 0x20 for a 16 chars and 2 line display #endif #ifdef _LCD_4BIT_ LiquidCrystal lcd(12, 11, 5, 4, 3, 2, BACKLIGHT_PIN, POSITIVE); #endif const int CONTRAST_PIN = 9; const int CONTRAST = 65; LCD *myLCD = &lcd; static double tempFilter; /*! @const charBitmap @abstract Define Character bitmap for the bargraph. @discussion Defines a character bitmap to represent a bargraph on a text display. The bitmap goes from a blank character to full black. */ const uint8_t charBitmap[][8] = { { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0 }, { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0 }, { 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x0 }, { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0 }, { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0 }, { 0xe, 0x11, 0x11, 0x11, 0xe, 0, 0, 0 }, { 0x6, 0x9, 0x9, 0x6, 0x0, 0, 0, 0} }; /*! @function @abstract Return available RAM memory @discussion This routine returns the ammount of RAM memory available after initialising the C runtime. @param @result Free RAM available. */ static int freeMemory() { int free_memory; if((int)__brkval == 0) free_memory = ((int)&free_memory) - ((int)&__bss_end); else free_memory = ((int)&free_memory) - ((int)__brkval); return free_memory; } /*! @function @abstract Returns AVR328p internal temperature @discussion Configures the ADC MUX for the temperature ADC channel and waits for conversion and returns the value of the ADC module @result The internal temperature reading - in degrees C */ static int readTemperature() { ADMUX = 0xC8; // activate interal temperature sensor, // using 1.1V ref. voltage ADCSRA |= _BV(ADSC); // start the conversion while (bit_is_set(ADCSRA, ADSC)); // ADSC is cleared when the conversion // finishes // combine bytes & correct for temperature offset (approximate) return ( (ADCL | (ADCH << 8)) - TEMP_CAL_OFFSET); } /*! @function @abstract Braws a bargraph onto the display representing the value passed. @discussion Draws a bargraph on the specified row using barLength characters. @param value[in] Value to represent in the bargraph @param row[in] Row of the LCD where to display the bargraph. Range (0, 1) for this display. @param barlength[in] Length of the bar, expressed in display characters. @param start[in] Start bar character @param end [in] End bar character @result None */ static void drawBars ( int value, uint8_t row, uint8_t barLength, char start, char end ) { int numBars; // Set initial titles on the display myLCD->setCursor (0, row); myLCD->print (start); // Calculate the size of the bar value = map ( value, -30, 50, 0, ( barLength ) * CHAR_WIDTH ); numBars = value / CHAR_WIDTH; // Limit the size of the bargraph to barLength if ( numBars > barLength ) { numBars = barLength; } myLCD->setCursor ( 1, row ); // Draw the bars while ( numBars-- ) { myLCD->print ( char( 5 ) ); } // Draw the fractions numBars = value % CHAR_WIDTH; myLCD->print ( char(numBars) ); myLCD->setCursor (barLength + 1, row); myLCD->print (end); } void setup () { int i; int charBitmapSize = (sizeof(charBitmap ) / sizeof (charBitmap[0])); Serial.begin ( 57600 ); analogReference ( INTERNAL ); #ifdef _LCD_4BIT_ pinMode(CONTRAST_PIN, OUTPUT); lcd.backlight(); digitalWrite(BACKLIGHT_PIN, HIGH); analogWrite (CONTRAST_PIN, CONTRAST); #else pinMode ( BACKLIGHT_PIN, OUTPUT ); digitalWrite(BACKLIGHT_PIN, HIGH); #endif myLCD->begin ( 16, 2 ); // Load custom character set into CGRAM for ( i = 0; i < charBitmapSize; i++ ) { myLCD->createChar ( i, (uint8_t *)charBitmap[i] ); } Serial.println ( freeMemory () ); myLCD->clear (); myLCD->print ("Temp:"); tempFilter = readTemperature (); // Initialise the temperature Filter } void loop () { int temp; temp = readTemperature(); tempFilter = ( FILTER_ALP * temp) + (( 1.0 - FILTER_ALP ) * tempFilter); myLCD->setCursor ( 8, 0 ); myLCD->print (" "); myLCD->setCursor ( 8, 0 ); myLCD->print ( tempFilter, 1 ); myLCD->setCursor ( 12, 0 ); myLCD->print ( "\x07" ); myLCD->print ("C"); drawBars ( tempFilter, 1, 14, '-', '+' ); delay (200); }