Overview

In previous lesson, we’ve learned how to output Raspberry Pi data through IIC (sometimes call I2C) and display characters in 1602 LCD . This lesson, we’ll  combine our knowledge learnt from Lesson 11 and Lesson 13. We will use a potentionmeter to change voltage, convert the voltage analog signal to digit signal through MCP3008 and send it to Pi via SPI. Then Pi will send  voltage data via I2C and display data on 1602 LCD screen.

Hardware Preparation:

1 * Raspberry Pi
1 * Breadboard
1 * Potentiometer(10kΩ)
1 * IIC 1602 LCD
Several jumper wires

Software Preparation
Note: In this lesson, we remotely control raspberry pi via PuTTy on PC. To learn how to config raspberry pi, please visit lesson 1: getting started with raspberry pi.

Potentiometer Work Principle

A Potentiometer is an adjustable resistor with three-terminal: two end terminals and a wiper.  it could create a variable resistor using one of the end terminals and the wipers by sliding wiper to adjust the resistor value. for more information ,please click here.

The construction and working of a Potentiometer can be understood from the below diagram, A and B are end terminals, C is wiper.

Hardware Setup

In this project, we’ll wire up the Pi with an external MCP3008 ADC, and measure the analog value via that. Then display the voltage value on 1602 LCD,The schematic as shown below:

 

Sample code

Regarding how to enable SPI and I2C, please read lesson10 and lesson13

for C language user


1)  Download the C sample code by typing following command in terminal:
cd   ~

sudo  wget http://osoyoo.com/driver/pi3_start_learning_kit_lesson_15/voltmeter.c

If you want to customize the sample code file , you can use nano editor to edit source code by typing following command:
sudo nano voltmeter.c

2) Compile code

gcc  -Wall  -o  voltmeter  voltmeter.c   -lwiringPi

3) Run the program

Before running program, please run command gpio  readall to check whether MOSI、MISO、SCLK(B10、B9、B11) works as alternative functions, If the terminal shows as following:
Please run the following command to change as alternative functions

gpio  -g  mode  9    alt0
gpio  -g  mode  10   alt0
gpio  -g  mode   11   alt0

If the terminal shows as the following, please go on running program

sudo  ./voltmeter

4) Running result

Once you run the program,the terminal will show print message as code firstly. the 1602 lcd will display the Potentiometer voltage, rotate the shaft of the potentiometer to adjust voltage between 0-3.3V.

C language Code Analysis

 
 
  1. #include < stdint.h>
  2. #include < string.h>
  3. #include < errno.h>
  4. #include < wiringPi.h>
  5. #include < stdio.h>
  6. #include < stdlib.h>
  7. #include < wiringPiSPI.h>
  8. #include < wiringPiI2C.h>
  9. #define LCDADDR 0x3F //IIC LCD address
  10. #define BLEN 1 //1--open backlight,0--close backlight
  11. #define CHAN_CONFIG_SINGLE 8 //setup channel 0 as Single-ended input
  12. #define SPICHANNEL 0 //MCP3008 connect to SPI0
  13. #define ANALOGCHANNEL 0 //Potentiometer connect MCP3008 analog channel 0
  14. static int spifd ;
  15. static int i2cfd;
  16. void spiSetup (int spiChannel)
  17. {
  18. if ((spifd = wiringPiSPISetup (spiChannel, 10000)) < 0)
  19. {
  20. fprintf (stderr, "Can't open the SPI bus: %s\n", strerror (errno)) ;
  21. exit (EXIT_FAILURE) ;
  22. }
  23. }
  24. int myAnalogRead(int spiChannel,int channelConfig,int analogChannel)
  25. {
  26. if(analogChannel7)
  27. return -1;
  28. unsigned char buffer[3] = {1}; // start bit
  29. buffer[1] = (channelConfig+analogChannel)
  30. wiringPiSPIDataRW(spiChannel, buffer, 3);
  31. return ( (buffer[1] & 3 )
  32. }
  33. void print_info()
  34. {
  35. printf("\n");
  36. printf("|************************************|\n");
  37. printf("| Voltemter |\n");
  38. printf("| ------------------------- |\n");
  39. printf("| | ADC | | Pi | |\n");
  40. printf("| |-----|-----------|-----| |\n");
  41. printf("| | CS | connect to| CE0 | |\n");
  42. printf("| | Din | connect to| MOSI| |\n");
  43. printf("| | Dout| connect to| MISO| |\n");
  44. printf("| | CLK | connect to| SCLK| |\n");
  45. printf("| | CH0 | connect to| 3.3V| |\n");
  46. printf("| | CH1 | connect to| GND | |\n");
  47. printf("|************************************|\n");
  48. printf("| Potentiometer connect to ADC CH0 |\n");
  49. printf("| OSOYOO|\n");
  50. printf("|************************************|\n");
  51. printf("\n");
  52. }
  53. //write a word to lcd
  54. void write_word(int data){
  55. int temp = data;
  56. if ( BLEN == 1 )
  57. temp |= 0x08;
  58. else
  59. temp &= 0xF7;
  60. wiringPiI2CWrite(i2cfd, temp);
  61. }
  62. //send command to lcd
  63. void send_command(int comm){
  64. int buf;
  65. // Send bit7-4 firstly
  66. buf = comm & 0xF0;
  67. buf |= 0x04; // RS = 0, RW = 0, EN = 1
  68. write_word(buf);
  69. delay(2);
  70. buf &= 0xFB; // Make EN = 0
  71. write_word(buf);
  72. // Send bit3-0 secondly
  73. buf = (comm & 0x0F)
  74. buf |= 0x04; // RS = 0, RW = 0, EN = 1
  75. write_word(buf);
  76. delay(2);
  77. buf &= 0xFB; // Make EN = 0
  78. write_word(buf);
  79. }
  80. //send data to lcd
  81. void send_data(int data){
  82. int buf;
  83. // Send bit7-4 firstly
  84. buf = data & 0xF0;
  85. buf |= 0x05; // RS = 1, RW = 0, EN = 1
  86. write_word(buf);
  87. delay(2);
  88. buf &= 0xFB; // Make EN = 0
  89. write_word(buf);
  90. // Send bit3-0 secondly
  91. buf = (data & 0x0F)
  92. buf |= 0x05; // RS = 1, RW = 0, EN = 1
  93. write_word(buf);
  94. delay(2);
  95. buf &= 0xFB; // Make EN = 0
  96. write_word(buf);
  97. }
  98. //initialize the lcd
  99. void init(){
  100. send_command(0x33); // Must initialize to 8-line mode at first
  101. delay(5);
  102. send_command(0x32); // Then initialize to 4-line mode
  103. delay(5);
  104. send_command(0x28); // 2 Lines & 5*7 dots
  105. delay(5);
  106. send_command(0x0C); // Enable display without cursor
  107. delay(5);
  108. send_command(0x01); // Clear Screen
  109. wiringPiI2CWrite(i2cfd, 0x08);
  110. }
  111. //clear screen
  112. void clear(){
  113. send_command(0x01); //clear Screen
  114. }
  115. //Print the message on the lcd
  116. void write(int x, int y, char data[]){
  117. int addr, i;
  118. int tmp;
  119. if (x < 0) x = 0; if (x > 15) x = 15;
  120. if (y < 0) y = 0; if (y > 1) y = 1;
  121. // Move cursor
  122. addr = 0x80 + 0x40 * y + x;
  123. send_command(addr);
  124. tmp = strlen(data);
  125. for (i = 0; i < tmp; i++){
  126. send_data(data[i]);
  127. }
  128. }
  129. int main()
  130. {
  131. int adc;
  132. float voltage;
  133. char buf[5];
  134. if(wiringPiSetup() < 0)
  135. { fprintf(stderr,"Can't init wiringPi: %s\n",strerror(errno));
  136. exit(EXIT_FAILURE);
  137. }
  138. spiSetup(SPICHANNEL);//init spi
  139. i2cfd = wiringPiI2CSetup(LCDADDR);//init i2c
  140. init();//init LCD
  141. clear();//clear screen
  142. print_info();
  143. while(1)
  144. {
  145. adc = myAnalogRead(SPICHANNEL,CHAN_CONFIG_SINGLE,ANALOGCHANNEL);
  146. voltage = adc/1024.*3.3;
  147. write(0,0,"Voltage:");
  148. sprintf(buf,"%1.2f",voltage);//float change to string
  149. write(8,0,buf);//print voltage on lcd
  150. write(12,0,"V");//print unit
  151. write(8,1,"--OSOYOO");
  152. delay(1000);
  153. }
  154. return 0;
  155. }

For python user, please take steps as following:


1) Download the python sample code by typing the command as followed:

cd  ~

sudo wget http://osoyoo.com/driver/pi3_start_learning_kit_lesson_15/voltmeter.py

If you want to customize the sample code file , you can use nano editor to edit source code by typing following command:
sudo nano voltmeter.py

2) Run the program

sudo  python  ./voltmeter.py

3) Running result

Once you run the program,the terminal will show print message as code firstly. the 1602 lcd will display the Potentiometer voltage, rotate the shaft of the potentiometer to adjust voltage between 0-3.3V.

Python sample code Analysis

 
 
  1. import time
  2. import os
  3. import RPi.GPIO as GPIO
  4. import smbus
  5. # Define some device parameters
  6. I2C_ADDR = 0x3F # I2C device address, if any error, change this address to 0x27
  7. LCD_WIDTH = 16 # Maximum characters per line
  8. # Define some device constants
  9. LCD_CHR = 1 # Mode - Sending data
  10. LCD_CMD = 0 # Mode - Sending command
  11. LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
  12. LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
  13. LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line
  14. LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line
  15. LCD_BACKLIGHT = 0x08 # On
  16. #LCD_BACKLIGHT = 0x00 # Off
  17. ENABLE = 0b00000100 # Enable bit
  18. # Timing constants
  19. E_PULSE = 0.0005
  20. E_DELAY = 0.0005
  21. # change these as desired - they're the pins connected from the
  22. # SPI port on the ADC to the Cobbler
  23. SPICLK = 11
  24. SPIMISO = 9
  25. SPIMOSI = 10
  26. SPICS = 8
  27. analogChannel = 0
  28. #Open I2C interface
  29. #bus = smbus.SMBus(0) # Rev 1 Pi uses 0
  30. bus = smbus.SMBus(1) # Rev 2 Pi uses 1
  31. #setup function for some setup---custom function
  32. def setup():
  33. #set the gpio modes to BCM numbering
  34. GPIO.setmode(GPIO.BCM)
  35. # set up the SPI interface pins
  36. GPIO.setup(SPIMOSI, GPIO.OUT)
  37. GPIO.setup(SPIMISO, GPIO.IN)
  38. GPIO.setup(SPICLK, GPIO.OUT)
  39. GPIO.setup(SPICS, GPIO.OUT)
  40. pass
  41. def lcd_init():
  42. # Initialise display
  43. lcd_byte(0x33,LCD_CMD) # 110011 Initialise
  44. lcd_byte(0x32,LCD_CMD) # 110010 Initialise
  45. lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction
  46. lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off
  47. lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size
  48. lcd_byte(0x01,LCD_CMD) # 000001 Clear display
  49. time.sleep(E_DELAY)
  50. def lcd_byte(bits, mode):
  51. # Send byte to data pins
  52. # bits = the data
  53. # mode = 1 for data
  54. # 0 for command
  55. bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
  56. bits_low = mode | ((bits
  57. return -1
  58. GPIO.output(cspin, True)
  59. GPIO.output(clockpin, False) # start clock low
  60. GPIO.output(cspin, False) # bring CS low
  61. commandout = adcnum
  62. commandout |= 0x18 # start bit + single-ended bit
  63. commandout
  64. for i in range(5):
  65. if (commandout & 0x80):
  66. GPIO.output(mosipin, True)
  67. else:
  68. GPIO.output(mosipin, False)
  69. commandout
  70. GPIO.output(clockpin, True)
  71. GPIO.output(clockpin, False)
  72. adcout = 0
  73. # read in one empty bit, one null bit and 10 ADC bits
  74. for i in range(12):
  75. GPIO.output(clockpin, True)
  76. GPIO.output(clockpin, False)
  77. adcout = 1 # first bit is 'null' so drop it
  78. return adcout
  79. #main function
  80. def main():
  81. #print info
  82. print_message()
  83. # Initialise display
  84. lcd_init()
  85. #clear screen
  86. lcd_byte(0x01, LCD_CMD)
  87. while True:
  88. adc = readadc(analogChannel, SPICLK, SPIMOSI, SPIMISO, SPICS)
  89. voltage = round((adc/1024.*3.3),2)
  90. voltage = str(voltage) #float change to string
  91. lcd_string("Voltage:
  92. lcd_string(voltage,LCD_LINE_2)
  93. time.sleep(1.5)
  94. #define a destroy function for clean up everything after the script finished
  95. def destroy():
  96. #release resource
  97. GPIO.cleanup()
  98. #
  99. # if run this script directly ,do:
  100. if __name__ == '__main__':
  101. setup()
  102. try:
  103. main()
  104. #when 'Ctrl+C' is pressed,child program destroy() will be executed.
  105. except KeyboardInterrupt:
  106. destroy()
  107. pass
  108. #clear screen
  109. finally:
  110. lcd_byte(0x01, LCD_CMD)

Leave a Reply

WordPress spam blocked by CleanTalk.
Bombax Theme designed by itx
"