Friday, 31 May 2019

temperature-monitor-using-msp430-launchpad-and-lm35-temperature-sensor

Here I summarize the hardware connections and source code to build a Temperature Monitor using MSP430 Launchpad and LM35 Sensor.
Project: Temperature Monitor with LCD Display
Microcontroller: MSP430G2231 on MSP-EXP430G2 Launchpad
Temperature Sensor: LM35
16×2 LCD Display: 1602K27-00

Hardware connections

Board jumper changes:
1. Isolate LEDs connected to P1.0 and P1.6 by removing Jumpers cap J5.
2. Isolate RX/TX connected to P1.1 and P1.2 by removing those Jumper cap in J3
Microcontroller and Temperature sensor Connections:
P1.1 – Vout of LM35
Microcontroller and LCD Connections
TP1 – Vcc (+5v)
TP3 – Vss (Gnd)
P1.2 – EN
P1.3 – RS
P1.4 – D4
P1.5 – D5
P1.6 – D6
P1.7 – D7
Gnd – RW
Gnd – Vee/Vdd – Connect to Gnd through a 1K Resistor – this value determines contrast – i.e. without resistor all dots always visible,  whereas higher resistor means dots not at all displayed.
Gnd – K (LED-)
Vcc – A (LED+) +5V – For Backlight
Clock: 1MHz
 Usage of LM35

Usage of LM35
Temperature Monitor Schematic
Temperature Monitor Schematic

This project is built using Energia IDE with integrated build tool chain (compiler/linker).

Source code

#include <msp430g2231.h>
#include <stdlib.h>
#include <string.h>
// uC GPIO Port assignment
#define UC_PORT      P1OUT
#define UC_PORT_DIR P1DIR
// LCD pin assignments
#define LCD_EN        BIT2
#define LCD_RS        BIT3
#define LCD_DATA    BIT4 | BIT5 | BIT6 | BIT7
#define LCD_D0_OFFSET 4 // D0 at BIT4, so it is 4
#define LCD_MASK    LCD_EN | LCD_RS | LCD_DATA
// Connect P1.1 to LM35 temperature sensor output
#define TEMP_IN      BIT1
char temperature_string[4];
short temperature = 0;
void lcd_reset()
{
UC_PORT = 0x00;
__delay_cycles(20000);
UC_PORT = (0x03 << LCD_D0_OFFSET) | LCD_EN;
UC_PORT &= ~LCD_EN;
__delay_cycles(10000);
UC_PORT = (0x03 << LCD_D0_OFFSET) | LCD_EN;
UC_PORT &= ~LCD_EN;
__delay_cycles(1000);
UC_PORT = (0x03 << LCD_D0_OFFSET) | LCD_EN;
UC_PORT &= ~LCD_EN;
__delay_cycles(1000);
UC_PORT = (0x02 << LCD_D0_OFFSET) | LCD_EN;
UC_PORT &= ~LCD_EN;
__delay_cycles(1000);
}
void lcd_cmd (char cmd)
{
// Send upper nibble
UC_PORT = (((cmd >> 4) & 0x0F) << LCD_D0_OFFSET) | LCD_EN;
UC_PORT &= ~LCD_EN;
// Send lower nibble
UC_PORT = ((cmd & 0x0F) << LCD_D0_OFFSET) | LCD_EN;
UC_PORT &= ~LCD_EN;
__delay_cycles(4000);
}
void lcd_data (unsigned char dat)
{
// Send upper nibble
UC_PORT = ((((dat >> 4) & 0x0F) << LCD_D0_OFFSET) | LCD_EN | LCD_RS);
UC_PORT &= ~LCD_EN;
// Send lower nibble
UC_PORT = (((dat & 0x0F) << LCD_D0_OFFSET) | LCD_EN | LCD_RS);
UC_PORT &= ~LCD_EN;
__delay_cycles(4000); // a small delay may result in missing char display
}
void lcd_init ()
{
UC_PORT_DIR = LCD_MASK;     // Output direction for LCD connections
lcd_reset();         // Call LCD reset
lcd_cmd(0x28);       // 4-bit mode – 2 line – 5×7 font.
lcd_cmd(0x0C);       // Display no cursor – no blink.
lcd_cmd(0x06);       // Automatic Increment – No Display shift.
lcd_cmd(0x80);       // Address DDRAM with 0 offset 80h.
lcd_cmd(0x01);     // Clear screen
}
void display_line(char *line)
{
while (*line)
lcd_data(*line++);
}
void display_temperature(char *line, int len)
{
while ((3-len) > 0)
lcd_data(‘ ‘);
while (len–) {
if (*line)
lcd_data(*line++);
}
lcd_data(0xDF); // degree symbol
lcd_data(‘C’);
}
void initADC(void)
{
// initialize 10-bit ADC
UC_PORT_DIR &= ~TEMP_IN;  // input direction for output from sensor
ADC10CTL0 |= ADC10ON;
ADC10CTL1 |= INCH_1|ADC10SSEL_1|CONSEQ_1;
ADC10AE0  |= BIT0 | BIT1;
ADC10CTL0 |= ENC|ADC10SC;
}
void setup() {
WDTCTL = WDTPW + WDTHOLD;   // Stop Watch Dog Timer
// Initialize LCD
lcd_init();
// Initialize ADC
initADC();
lcd_cmd(0x80); // select 1st line (0x80 + addr) – here addr = 0x00
display_line(“Temperature”);
lcd_cmd(0xce); // select 2nd line (0x80 + addr) – here addr = 0x4e
}
void loop() {
// measuring the temperature
temperature = (analogRead(A1)*35)/100;
// displaying the current temperature
lcd_cmd(0xcb); // select 2nd line (0x80 + addr) – here addr = 0x4b
itoa(temperature, temperature_string, 10);
display_temperature(temperature_string, 3);
__delay_cycles(500000);       // 0.5sec measurement cycle
}
You can also download source code
  Temperature_Monitor.ino (3.1 KiB, 1,076 hits)
Temperature_Monitor.ino - this is basically a C source file in Energia IDE format.
Temperature Monitor in action

Temperature Monitor in action

u-boot-tools-for-debian-arm-linux-in-qnap-server

Here is a small note on how to install U-Boot tools to manage boot loader from linux environment. This will provide a tool for printing environment for the bootloader U-Boot (fw_printenv) and modifying the same (fw_setenv).
1. Install the necessary U-Boot support packages
# apt-get install u-boot uboot-envtools
You can find your MTD partition information in /proc/mtd file as shown below.
# cat /proc/mtd
dev: size erasesize name
mtd0: 00080000 00040000 “U-Boot”
mtd1: 00200000 00040000 “Kernel”
mtd2: 00900000 00040000 “RootFS1”
mtd3: 00300000 00040000 “RootFS2”
mtd4: 00040000 00040000 “U-Boot Config”
mtd5: 00140000 00040000 “NAS Config”
2. Create a configuration file /etc/fw_env.config for U-boot environment in the machine. In my case it is QNAP TS-110 Home Server. Here is the configuration file.
# Configuration file for fw_(printenv/saveenv) utility for
# QNAP TS-119, TS-219 and TS-219P.
# MTD device name Device offset Env. size Flash sector size
/dev/mtd4 0x0000 0x1000 0x40000
You have good chances of getting fw_env.config file for your machine in /usr/share/doc/uboot-envtools/examples (installed by uboot-envtools).
In case you don’t have the above file, you will end up with the following error message while issuing the fw_printenv command.
# fw_printenv
Cannot parse config file: No such file or directory
As an another error case, if you have wrong configuration file it will throw the following error message.
# fw_printenv
Warning: Bad CRC, using default environment
bootcmd=bootp; setenv bootargs root=/dev/nfs nfsroot=${serverip}:${rootpath} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}::off; bootm
bootdelay=5
baudrate=115200
Here is the output of fw_printenv command in my server.
# fw_printenv  
baudrate=115200
loads_echo=0
rootpath=/mnt/ARM_FS/
console=console=ttyS0,115200 mtdparts=cfi_flash:0xf40000(root),0xc0000(uboot)ro
CASset=min
MALLOC_len=1
ethprime=egiga0
bootargs_root=root=/dev/nfs rw
bootargs_end=:::DB88FXX81:eth0:none
image_name=uImage
standalone=fsload 0x2000000 $(image_name);setenv bootargs $(console) root=/dev/mtdblock0 rw ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvPhoneConfig); bootm 0x2000000;
ethaddr=00:08:XX:XX:XX:XX
mvPhoneConfig=mv_phone_config=dev0:fxs,dev1:fxo
mvNetConfig=mv_net_config=(00:11:88:0f:62:81,0:1:2:3),mtu=1500
usb0Mode=host
yuk_ethaddr=00:00:00:EE:51:81
netretry=no
rcvrip=169.254.100.100
loadaddr=0x02000000
autoload=no
ethact=egiga0
update=tftp 0x800000 uImage; tftp 0xa00000 rootfs.gz;bootm 0x800000
filesize=36464c
fileaddr=A00000
bootcmd=uart1 0x68;cp.l 0xf8200000 0x800000 0x80000;cp.l 0xf8400000 0xa00000 0x240000;bootm 0x800000
ipaddr=172.17.21.248
serverip=172.17.21.7
netmask=255.255.254.0
bootargs=console=ttyS0,115200 root=/dev/ram initrd=0xa00000,0x900000 ramdisk=32768
stdin=serial
stdout=serial
stderr=serial
mainlineLinux=no
enaMonExt=no
enaCpuStream=no
enaWrAllo=no
pexMode=RC
disL2Cache=no
setL2CacheWT=yes
disL2Prefetch=yes
enaICPref=yes
enaDCPref=yes
sata_dma_mode=yes
netbsd_en=no
vxworks_en=no
bootdelay=3
disaMvPnp=no
enaAutoRecovery=yes
bootp_vendor_class=F_TS-110
3. To modify the U-boot parameter, you can use fw_setenv command. Here is an example of how to change boot delay.
# fw_setenv bootdelay 5