正規のオンライン小売業者:
前のレッスンでは、Raspberry PiのデータをIIC(I2Cとも呼ばれる)を介して出力し、1602 LCDに文字を表示する方法を学びました。今回のレッスンでは、レッスン11とレッスン13で学んだ知識を組み合わせます。ポテンショメータを使用して電圧を変更し、MCP3008を介してアナログ信号をデジタル信号に変換し、SPIを介してPiに送信します。その後、PiはI2Cを介して電圧データを送信し、1602 LCD画面にデータを表示します。
1 * Raspberry Pi
1 * ブレッドボード
1 * ポテンショメータ(10kΩ)
1 * IIC 1602 LCD
数本のジャンパーワイヤー
ソフトウェアの準備
注:このレッスンでは、PC上のPuTTyを使用してRaspberry Piをリモートで制御します。Raspberry Piの設定方法については、lesson 1: getting started with raspberry piをご覧ください。
ポテンショメータは、2つの端子とワイパーを持つ可変抵抗器であり、ワイパーをスライドして抵抗値を調整することで、端子の1つとワイパーを使用して可変抵抗器を作成することができます。詳細については、hereをクリックしてください。
ポテンショメータの構造と動作は、以下の図から理解できます。AとBは端子で、Cはワイパーです。
このプロジェクトでは、Piを外部のMCP3008 ADCに配線し、そこからアナログ値を測定します。その後、1602 LCDに電圧値を表示します。回路図は以下のようになります。
SPIとI2Cを有効にする方法については、lesson10 and lesson13を読んでください。
C言語ユーザーの場合
1)ターミナルに以下のコマンドを入力して、Cのサンプルコードをダウンロードします。
cd ~
sudo wget http://osoyoo.com/driver/pi3_start_learning_kit_lesson_15/voltmeter.c
サンプルコードファイルをカスタマイズしたい場合は、次のコマンドを入力してnanoエディターを使用してソースコードを編集することができます:
sudo nano voltmeter.c
2)コードをコンパイルする
gcc -Wall -o voltmeter voltmeter.c -lwiringPi
3) プログラムを実行する
プログラムを実行する前に、コマンド gpio readall を実行して、MOSI、MISO、SCLK(B10、B9、B11) が代替機能として機能するかどうかを確認してください。ターミナルが次のように表示される場合:
代替機能として変更するには、次のコマンドを実行してください
gpio -g mode 9 alt0
gpio -g mode 10 alt0
gpio -g mode 11 alt0
ターミナルが次のように表示されたら、プログラムを実行してください。
sudo ./voltmeter
4) 実行結果
プログラムを実行すると、ターミナルにはまずコードの印刷メッセージが表示されます。1602 LCDには、ポテンショメータの電圧が表示され、ポテンショメータのシャフトを回して0〜3.3Vの間の電圧を調整します。
C 言語コードの解析
#include < stdint.h> #include < string.h> #include < errno.h> #include < wiringPi.h> #include < stdio.h> #include < stdlib.h> #include < wiringPiSPI.h> #include < wiringPiI2C.h> #define LCDADDR 0x3F //IIC LCD address #define BLEN 1 //1--open backlight,0--close backlight #define CHAN_CONFIG_SINGLE 8 //setup channel 0 as Single-ended input #define SPICHANNEL 0 //MCP3008 connect to SPI0 #define ANALOGCHANNEL 0 //Potentiometer connect MCP3008 analog channel 0 static int spifd ; static int i2cfd; void spiSetup (int spiChannel) { if ((spifd = wiringPiSPISetup (spiChannel, 10000)) < 0) { fprintf (stderr, "Can't open the SPI bus: %s\n", strerror (errno)) ; exit (EXIT_FAILURE) ; } } int myAnalogRead(int spiChannel,int channelConfig,int analogChannel) { if(analogChannel7) return -1; unsigned char buffer[3] = {1}; // start bit buffer[1] = (channelConfig+analogChannel) << 4; wiringPiSPIDataRW(spiChannel, buffer, 3); return ( (buffer[1] & 3 ) << 8 ) + buffer[2]; // get last 10 bits } void print_info() { printf("\n"); printf("|************************************|\n"); printf("| Voltemter |\n"); printf("| ------------------------- |\n"); printf("| | ADC | | Pi | |\n"); printf("| |-----|-----------|-----| |\n"); printf("| | CS | connect to| CE0 | |\n"); printf("| | Din | connect to| MOSI| |\n"); printf("| | Dout| connect to| MISO| |\n"); printf("| | CLK | connect to| SCLK| |\n"); printf("| | CH0 | connect to| 3.3V| |\n"); printf("| | CH1 | connect to| GND | |\n"); printf("|************************************|\n"); printf("| Potentiometer connect to ADC CH0 |\n"); printf("| OSOYOO|\n"); printf("|************************************|\n"); printf("\n"); } //write a word to lcd void write_word(int data){ int temp = data; if ( BLEN == 1 ) temp |= 0x08; else temp &= 0xF7; wiringPiI2CWrite(i2cfd, temp); } //send command to lcd void send_command(int comm){ int buf; // Send bit7-4 firstly buf = comm & 0xF0; buf |= 0x04; // RS = 0, RW = 0, EN = 1 write_word(buf); delay(2); buf &= 0xFB; // Make EN = 0 write_word(buf); // Send bit3-0 secondly buf = (comm & 0x0F) << 4; buf |= 0x04; // RS = 0, RW = 0, EN = 1 write_word(buf); delay(2); buf &= 0xFB; // Make EN = 0 write_word(buf); } //send data to lcd void send_data(int data){ int buf; // Send bit7-4 firstly buf = data & 0xF0; buf |= 0x05; // RS = 1, RW = 0, EN = 1 write_word(buf); delay(2); buf &= 0xFB; // Make EN = 0 write_word(buf); // Send bit3-0 secondly buf = (data & 0x0F) << 4; buf |= 0x05; // RS = 1, RW = 0, EN = 1 write_word(buf); delay(2); buf &= 0xFB; // Make EN = 0 write_word(buf); } //initialize the lcd void init(){ send_command(0x33); // Must initialize to 8-line mode at first delay(5); send_command(0x32); // Then initialize to 4-line mode delay(5); send_command(0x28); // 2 Lines & 5*7 dots delay(5); send_command(0x0C); // Enable display without cursor delay(5); send_command(0x01); // Clear Screen wiringPiI2CWrite(i2cfd, 0x08); } //clear screen void clear(){ send_command(0x01); //clear Screen } //Print the message on the lcd void write(int x, int y, char data[]){ int addr, i; int tmp; if (x < 0) x = 0; if (x > 15) x = 15; if (y < 0) y = 0; if (y > 1) y = 1; // Move cursor addr = 0x80 + 0x40 * y + x; send_command(addr); tmp = strlen(data); for (i = 0; i < tmp; i++){ send_data(data[i]); } } int main() { int adc; float voltage; char buf[5]; if(wiringPiSetup() < 0) { fprintf(stderr,"Can't init wiringPi: %s\n",strerror(errno)); exit(EXIT_FAILURE); } spiSetup(SPICHANNEL);//init spi i2cfd = wiringPiI2CSetup(LCDADDR);//init i2c init();//init LCD clear();//clear screen print_info(); while(1) { adc = myAnalogRead(SPICHANNEL,CHAN_CONFIG_SINGLE,ANALOGCHANNEL); voltage = adc/1024.*3.3; write(0,0,"Voltage:"); sprintf(buf,"%1.2f",voltage);//float change to string write(8,0,buf);//print voltage on lcd write(12,0,"V");//print unit write(8,1,"--OSOYOO"); delay(1000); } return 0; }
Pythonユーザーの場合は、以下の手順を実行してください。
1) 次のコマンドを入力してPythonのサンプルコードをダウンロードします。
cd ~
sudo wget http://osoyoo.com/driver/pi3_start_learning_kit_lesson_15/voltmeter.py
サンプルコードファイルをカスタマイズしたい場合は、次のコマンドを入力してnanoエディターを使用してソースコードを編集することができます:
sudo nano voltmeter.py
2) プログラムを実行する
sudo python ./voltmeter.py
3) 実行結果
プログラムを実行すると、ターミナルにはまずコードの印刷メッセージが表示されます。1602 LCDには、ポテンショメータの電圧が表示され、ポテンショメータのシャフトを回して0〜3.3Vの間の電圧を調整します。
Pythonのサンプルコードの解析
import time import os import RPi.GPIO as GPIO import smbus # Define some device parameters I2C_ADDR = 0x3F # I2C device address, if any error, change this address to 0x27 LCD_WIDTH = 16 # Maximum characters per line # Define some device constants LCD_CHR = 1 # Mode - Sending data LCD_CMD = 0 # Mode - Sending command LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line LCD_BACKLIGHT = 0x08 # On #LCD_BACKLIGHT = 0x00 # Off ENABLE = 0b00000100 # Enable bit # Timing constants E_PULSE = 0.0005 E_DELAY = 0.0005 # change these as desired - they're the pins connected from the # SPI port on the ADC to the Cobbler SPICLK = 11 SPIMISO = 9 SPIMOSI = 10 SPICS = 8 analogChannel = 0 #Open I2C interface #bus = smbus.SMBus(0) # Rev 1 Pi uses 0 bus = smbus.SMBus(1) # Rev 2 Pi uses 1 #setup function for some setup---custom function def setup(): #set the gpio modes to BCM numbering GPIO.setmode(GPIO.BCM) # set up the SPI interface pins GPIO.setup(SPIMOSI, GPIO.OUT) GPIO.setup(SPIMISO, GPIO.IN) GPIO.setup(SPICLK, GPIO.OUT) GPIO.setup(SPICS, GPIO.OUT) pass def lcd_init(): # Initialise display lcd_byte(0x33,LCD_CMD) # 110011 Initialise lcd_byte(0x32,LCD_CMD) # 110010 Initialise lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size lcd_byte(0x01,LCD_CMD) # 000001 Clear display time.sleep(E_DELAY) def lcd_byte(bits, mode): # Send byte to data pins # bits = the data # mode = 1 for data # 0 for command bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT bits_low = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT # High bits bus.write_byte(I2C_ADDR, bits_high) lcd_toggle_enable(bits_high) # Low bits bus.write_byte(I2C_ADDR, bits_low) lcd_toggle_enable(bits_low) def lcd_toggle_enable(bits): # Toggle enable time.sleep(E_DELAY) bus.write_byte(I2C_ADDR, (bits | ENABLE)) time.sleep(E_PULSE) bus.write_byte(I2C_ADDR,(bits & ~ENABLE)) time.sleep(E_DELAY) def lcd_string(message,line): # Send string to display message = message.ljust(LCD_WIDTH," ") lcd_byte(line, LCD_CMD) for i in range(LCD_WIDTH): lcd_byte(ord(message[i]),LCD_CHR) #print message at the begining ---custom function def print_message(): print ('|**********************************|') print ('| Voltmeter |') print ('| ------------------------- |') print ('| | ADC | | Pi | |') print ('| |-----|-----------|-----| |') print ('| | CS | connect to| CE0 | |') print ('| | Din | connect to| MOSI| |') print ('| | Dout| connect to| MISO| |') print ('| | CLK | connect to| SCLK| |') print ('| | CH0 | connect to| 3.3V| |') print ('| | CH1 | connect to| GND | |') print ('| ------------------------- |') print ('| Potentiometer connect to CH0 |') print ('| OSOYOO|') print ('|**********************************|\n') print ('Program is running...') print ('Please press Ctrl+C to end the program...') # read SPI data from MCP3008 chip, 8 possible adc's (0 thru 7) def readadc(adcnum, clockpin, mosipin, misopin, cspin): if ((adcnum > 7) or (adcnum < 0)): return -1 GPIO.output(cspin, True) GPIO.output(clockpin, False) # start clock low GPIO.output(cspin, False) # bring CS low commandout = adcnum commandout |= 0x18 # start bit + single-ended bit commandout <<= 3 # we only need to send 5 bits here for i in range(5): if (commandout & 0x80): GPIO.output(mosipin, True) else: GPIO.output(mosipin, False) commandout <<= 1 GPIO.output(clockpin, True) GPIO.output(clockpin, False) adcout = 0 # read in one empty bit, one null bit and 10 ADC bits for i in range(12): GPIO.output(clockpin, True) GPIO.output(clockpin, False) adcout <<= 1 if (GPIO.input(misopin)): adcout |= 0x1 GPIO.output(cspin, True) adcout >>= 1 # first bit is 'null' so drop it return adcout #main function def main(): #print info print_message() # Initialise display lcd_init() #clear screen lcd_byte(0x01, LCD_CMD) while True: adc = readadc(analogChannel, SPICLK, SPIMOSI, SPIMISO, SPICS) voltage = round((adc/1024.*3.3),2) voltage = str(voltage) #float change to string lcd_string("Voltage: <",LCD_LINE_1) lcd_string(voltage,LCD_LINE_2) time.sleep(1.5) #define a destroy function for clean up everything after the script finished def destroy(): #release resource GPIO.cleanup() # # if run this script directly ,do: if __name__ == '__main__': setup() try: main() #when 'Ctrl+C' is pressed,child program destroy() will be executed. except KeyboardInterrupt: destroy() pass #clear screen finally: lcd_byte(0x01, LCD_CMD)
DownLoad Url osoyoo.com
You must be logged in to post a comment.
Where is the function to toggle the backlight on/off?
You can turn around the Potentiometer at the back of LCD to adjust LCD backlight
I know about the potentiometer. But i am asking about the function to turn off the backlight from the python code. the backlight consumes too much battery so i need to put it to sleep for some time.