Raspberry Pi and PCF8591 analog-to-digital converter


1. Introduction

  Because there is no built-in analog-to-digital converter (ADC) on the Raspberry Pi, when we need to use the Raspberry Pi to read analog data, we need to connect an external converter (ADC) with analog-to-digital conversion function. This article uses PCF8591. HW-011, according to the reference example, successfully reproduced the led light.

Experimental result

2. Hardware preparation

1、PCF8591 * 1

  PCF8591 is a monolithic integrated, separate power supply, low power consumption, 8-bit CMOS data acquisition device. PCF8591 has 4 analog inputs, 1 analog output and 1 serial I²C bus interface. The 3 address pins A0, A1 and A2 of PCF8591 can be used for hardware address programming, allowing 8 PCF8591 devices to be connected to the same I2C bus without additional hardware. The address, control and data signals input and output on the PCF8591 device are all transmitted in a serial manner through the two-wire bidirectional I2C bus.
PCF8591

2. KY-011 two-color LED module * 1

  Ky-011 is divided into two colors of red and yellow, (left side in the picture) the pin marked with'-' is connected to GND, the middle pin control lights up red, (right side in the picture) the pin marked "S" controls light up Yellow light.
Insert picture description here

3. Raspberry Pi 4B * 1

Insert picture description here

4. Hardware pin connection

Pin connection
  Because there are a lot of wiring in the later experiment, in order to facilitate the wiring, the GPIO expansion board is used. This can be bought at a random search in a treasure, usually ranging from a few yuan to a dozen yuan. It is recommended that you spend more money Buy a better one, after all, you get what you pay for. The picture above is a wiring diagram made by Chuanglebo. There are more than 30 experiments and a complete set of development kits. At present, most of the tutorials found on the Internet are also referred to here.

Raspberry Pi Expansion Board PCF8591
SCL SCL
SDA SDA
5V VCC
GND GND

  Here, Y will be used to replace the yellow light pin, R represents the red light pin, and * represents nothing. Of course, this one is the same if it is connected to yellow and red. It is a simulation experiment. The PCF8591 outputs the signal to the LED to make it light. light. In addition, the J6 short-circuit cap cannot be removed, and the rest are free

PCF8591 KY-011 Led
AUGUST AND
* R
GND GND

Three, software preparation

  The principle is very simple. It is to obtain the input voltage adjusted by the blue potentiometer through the PCF8591, and convert it into a digital value for display on the terminal, and then convert it into an analog value from the AOUT output to achieve the purpose of lighting.

  In addition, if you want to achieve the effect, you must first open the I2C interface of the Raspberry Pi, which is closed by default in the Raspberry Pi. When using the sensor, we must first allow I2C bus communication.
Insert picture description here

1、PCF8591.py

  PCF8591.py can be run alone to achieve the effect of LED lighting.

#!/usr/bin/env python
#------------------------------------------------------
#
#       This is a program for PCF8591 Module. 
#
#       Warnng! The Analog input MUST NOT be over 3.3V!
#    
#       In this script, we use a poteniometer for analog
#   input, and a LED on AO for analog output. 
#
#       you can import this script to another by:
#   import PCF8591 as ADC
#   
#   ADC.Setup(Address)  # Check it by sudo i2cdetect -y -1
#   ADC.read(channal)   # Channal range from 0 to 3
#   ADC.write(Value)    # Value range from 0 to 255     
#
#------------------------------------------------------
#SMBus (System Management Bus,系统管理总线) 
import smbus   #在程序中导入“smbus”模块
import time

# for RPI version 1, use "bus = smbus.SMBus(1)"
# 0 代表 /dev/i2c-0, 1 代表 /dev/i2c-1 ,具体看使用的树莓派那个I2C来决定
bus = smbus.SMBus(1)         #创建一个smbus实例

#在树莓派上查询PCF8591的地址:“sudo i2cdetect -y 1”
def setup(Addr):
	global address
	address = Addr

def read(chn): #channel
	if chn == 0:
		bus.write_byte(address,0x40)   #发送一个控制字节到设备
	if chn == 1:
		bus.write_byte(address,0x41)
	if chn == 2:
		bus.write_byte(address,0x42)
	if chn == 3:
		bus.write_byte(address,0x43)
	bus.read_byte(address)         # 从设备读取单个字节,而不指定设备寄存器。
	return bus.read_byte(address)  #返回某通道输入的模拟值A/D转换后的数字值

def write(val):
	temp = val  # 将字符串值移动到temp
	temp = int(temp) # 将字符串改为整数类型
	# print temp to see on terminal else comment out
	bus.write_byte_data(address, 0x40, temp) 
    #写入字节数据,将数字值转化成模拟值从AOUT输出

if __name__ == "__main__":
	setup(0x48) 
 #在树莓派终端上使用命令“sudo i2cdetect -y 1”,查询出PCF8591的地址为0x48
	while True:
		print ('电位计   AIN0 = ', read(0))   #电位计模拟信号转化的数字值
		print ('光敏电阻 AIN1 = ', read(1))   #光敏电阻模拟信号转化的数字
        print ('热敏电阻 AIN2 = ', read(2))   #热敏电阻模拟信号转化的数字值
		tmp = read(0)
		tmp = tmp*(255-125)/255+125 
# 125以下LED不会亮,所以将“0-255”转换为“125-255”,调节亮度时灯不会熄灭
		write(tmp)
		time.sleep(2)

2、main.py

  Import PCF8591, and only print the digital value after A/D conversion of the potentiometer voltage.

#!/usr/bin/env python
import PCF8591 as ADC

def setup():
	ADC.setup(0x48)

def loop():
	while True:
		print ADC.read(0) 
  #打印电位计电压大小A/D转换后的数字值(从AIN0借口输入的)
  #范围是0~255,0时LED灯熄灭,255时灯最亮
		ADC.write(ADC.read(0)) 
  #将0通道输入的电位计电压数字值转化成模拟值从AOUT输出
  #给LED灯提供电源VCC输入

def destroy():
	ADC.write(0)

if __name__ == "__main__":
	try:
		setup()
		loop()
	except KeyboardInterrupt:
		destroy()

3. Experimental results

  After running the program, the led light is lit, adjust the blue potentiometer, the brightness of the led light changes.
Experimental result
  Shell displays the digital value of potentiometer, photoresistor, and thermistor.
Experimental result 2
  But because the written tmp is added 125, it always keeps a brighter situation, so adjust the potentiometer, the led light will not have obvious changes in brightness, you can try to remove it when you test.
Insert picture description here
  Manually adjust it to 0,100,200, the brightness of the led light:
manual adjustment

4. C program

#include <wiringPi.h>
#include <pcf8591.h>
#include <stdio.h>
#include <time.h>

//PCF8591默认的I2C设备地址
#define Address 0x48

//模拟信号输入端的地址
#define BASE 0x40
#define A0 0x40
#define A1 0x41
#define A2 0x42
#define A3 0x43

//供电(mV)
#define POWER 5000

//函数声明
void ShowTime();
float AD_work(unsigned char channel);

int main(void)
{
    
    
	//初始化wiringPi设置
	wiringPiSetup();

	//设置pcf8591的器件地址
	pcf8591Setup(BASE, Address);

	float AD_val;

	while (1)
	{
    
    
		AD_val=AD_work(A0);//读取A0端口的电压值
		
		ShowTime(); //打印当前时间
		
		printf("A0 value: %fmV\n", AD_val); //打印A0引脚的输入电压
		//printf("asgydasg");
		
		delay(100);
	}
}

//显示系统时间
void ShowTime()
{
    
    
	time_t t;
	struct tm *p;
	int hour = 0, min = 0, sec = 0;
	time(&t);
	p = gmtime(&t);
	hour = 8 + p->tm_hour; //获取当地时间,与UTC时间相差8小时
	min = p->tm_min;
	sec = p->tm_sec;
	printf("\nNow time: %.2d:%.2d:%.2d\n", hour, min, sec);
}

float AD_work(unsigned char channel)
{
    
    
	float AD_val; //定义处理后的数值AD_val为浮点数
	unsigned char i;
	for (i = 0; i < 10; i++) 
		AD_val += analogRead(channel); //转换10次求平均值(提高精度)
	AD_val /= 10;
	AD_val = (AD_val * POWER)/ 255 ; //AD的参考电压是单片机上的5v,所以乘5即为实际电压值
	return AD_val;
}

Insert picture description here
Experimental results:
C experiment results

Four, knowledge preparation

1. Detailed explanation of PCF8591

  ​ PCF8591 is an 8-bit analog-to-digital converter or 8-bit digital-to-analog converter module, which means that each pin can read analog values ​​up to 0-255; the module has four analog inputs and one analog output, and It is suitable for I2C communication; in addition, it requires 2.5V-6V power supply voltage and has a low standby current. We can control the input voltage by adjusting the knob of the blue potentiometer. There are also three jumpers on the board. The J4 connection selects the thermistor access circuit, the J5 connection selects the LDR/photoresistor access circuit and the J6 connection selects the 0-5V adjustable voltage access circuit. To access these circuits, the addresses of these jumpers must be used: J6 is 0x50, J5 is 0x60, and J4 is 0x70. There are two LEDs on the circuit board, D1 and D2, D1 represents the output voltage intensity, and D2 represents the power supply voltage intensity. The higher the output or power supply voltage, the higher the intensity of LED D1 or D2.
PCF8591

1.1. Module function description

  • 1 The module chip uses PCF8951
  • 2 The module supports external 4 channels of voltage input collection (voltage input range 0-5v)
  • 3 The module integrates a photoresistor, which can collect accurate values ​​of ambient light intensity through AD
  • 4 The module integrates thermistor, which can collect accurate values ​​of ambient temperature through AD
  • 5 The module integrates 1 channel 0-5V voltage input acquisition (adjust the input voltage through the blue potentiometer)
  • 6 The module has a power indicator (the indicator will be on after the module is powered)
  • 7 The module has a DA output indicator. When the voltage of the DA output interface of the module reaches a certain value, the DA output indicator on the board will light up. The higher the voltage, the more obvious the brightness of the indicator;

1.2. Module interface description

The left and right sides of this module are respectively expanded with 2 pin headers, respectively, as follows:
pcf8591 module diagram
Left:

  • AOUT: chip DA output interface
  • AIN0: chip analog input interface 0
  • AIN1: chip analog input interface 1
  • AIN2: chip analog input interface 2
  • AIN3: chip analog input interface 3

right:

  • SCL: IIC clock interface connects to MCU IO port
  • SDA: IIC digital interface connects to MCU IO port
  • GND: external grounding of the module ground
  • VCC: External 3.3v-5v power interface

There are 3 short-circuit caps in the module, and their functions are as follows:
J4: connect the J4 short-circuit cap, select the thermistor access circuit
J5: connect the J5 short-circuit cap, select the photoresistor access circuit
J6: connect the J6 short-circuit cap, select 0 -5V adjustable voltage access circuit

Note: If you need to use four external voltage inputs, please remove all three red shorting caps

1.3, module schematic diagram

PCF8591 schematic
Insert picture description here

1.4. Module principle description

  ​ PCF8591 is the AIN port input analog voltage, and then PCF8591 sends the converted digital quantity I2Cto the single-chip microcomputer through the I2Cbus , or the single-chip microcomputer sends a digital quantity through the bus, and then PCF8591 outputs the analog voltage through the AOUT port.

First byte: bus address

  For the use of PCF8591, follow the steps of searching the address first and then reading and writing the corresponding register. The address that the PCF8591 chip can receive includes a fixed part and a programmable part. The programmable part must A0,A1,和A2be set according to the address pin . In the I2Cbus protocol, the address must be sent as the first byte after the start condition, and the last bit of the address byte is used to set the read or write to the target address. The address byte format is as follows:
Address byte
  PCF8591 uses a typical I2C bus interface device addressing method, that is, the bus address is composed of device address, pin address and direction bit. Philips stipulates that the A/D device address is 1001 , and the pin address is A2A1A0. The value is selected by the user. Therefore, the I2C system can be connected to the third power of 2 = 8 A/D devices with I2C bus interface. The last bit of the address is the direction bit R/W, which is 1 when the main controller reads the A/D device, and 0 when the write operation is performed. During bus operation, the slave address composed of device address, pin address and direction bit is the first byte sent by the master.

  For PCF8591, its default address is 0x48 (hexadecimal number), and converted to binary number is 1001000, so it can be known that the values ​​of his three pins A0, A1, and A2 are all 0. It needs to be emphasized in advance that all 0x hexadecimal numbers in the Python code, only 0x48 represents Address , and only PCF has Address, and all other hexadecimal numbers do not represent Address.

The second byte: the first byte of the control byte
  is the address byte, then the second byte is the control byte, the control byte is sent to the control register of PCF8591, used to control the function of the device, the control word format As shown below:
Control byte
Sketch map:
Insert picture description here
Among them:

  • D1, D0, two digits are the A/D channel numbers: 00 channel 0, 01 channel 1, 10 channel 2, 11 channel 3
  • D2 Auto increment selection (0 means auto increment is prohibited, 1 means auto increment is allowed), if auto increment is allowed, the channel number will automatically increase after each A/D conversion.
  • D3 feature bit: fixed value: 0.
  • D5, D4 analog input options: 00 is four single-ended inputs, 01 is three differential inputs, 10 is two single-ended and one differential inputs, and 11 is two differential inputs.
  • D6 enables the analog output AOUT to be valid (1 is valid, 0 is invalid).
  • D7 feature bit: fixed value: 0.

  The "bus.write_byte(address,0x40)" statement encountered in programming is to send the control word "0x40", 40 represents the control word "0100 0000", which mainly means that the analog output is valid, four single-ended inputs, and automatic increment is prohibited , A/D channel is 0.
Insert picture description here

  When the system is A/D conversion, the analog output is allowed to be 0. The value of the analog input selection bit is determined by the input mode: 00 for four-channel single-ended input, 01 for three-channel differential input, 10 for single-ended and differential input, and 11 for two-channel differential input. The lowest two digits are the channel number bits. It is 00 when the analog signal of channel 0 is A/D converted, and 01 is used when the analog signal of channel 1 is A/D converted. When the analog signal of channel 2 is A/D converted, it is set to 01. Take 10 for D conversion, and take 11 when performing A/D conversion on the 3-channel analog signal.

  When performing data operations, first the master controller sends out the start signal, and then sends out the read address byte. After the controller responds, the master controller reads the first data byte from the controller, and the master controller The master controller sends a response, the master controller reads the second data byte from the controlled device, and the master controller sends a response...until the master controller reads the nth data byte from the controlled device, and the master controller sends a non Answer the signal, and finally the main controller sends a stop signal.

1.5, D/A conversion

Insert picture description here
  The third byte sent to PCF8591 is stored in the DAC data register and converted into the corresponding analog voltage using the on-chip D/A converter.
Conversion formula
  We can use the conversion formula to convert the digital quantity after the AD conversion to the corresponding voltage value and display it on the digital tube or liquid crystal.

#define fun(x) (int)(5*x/255.0*100+0.5)             //数字电压x转换为模拟电压的公式

1.6, A/D conversion

Insert picture description here
  The A/D converter adopts successive approximation conversion technology. The on-chip D/A converter and high-gain comparator will be temporarily used during the A/D conversion cycle. An A/D conversion cycle always starts by sending a valid read mode address to PCF8591 After that, the A/D conversion cycle is triggered on the back edge of the response clock pulse and executed when the previous conversion result is transmitted.

1.7, the relationship between PCF8591 and Raspberry Pi

Insert picture description here
  Consider the entire system as a water inlet/outlet device. The device has four inlet pipes, named AIN0, AIN1, AIN2, AIN3, and the only outlet pipe, named AOUT. There are also four transfer channels, named channel0, channel1, channel2, and channel3 respectively. The water from the four inlet pipes can flow out of a certain channel under control, enter the main pipe, and then pass through two outlet pipes-SDA And SCL, enter a water processing and storage facility.

  Raspberry PI is "MASTER", PCF is "SLAVER", and they have a master-slave relationship. If the master device wants to send data to the slave device, it will start the data transmission, and send the data to the slave device, and finally terminate the data transmission; if the master device wants to accept the data sent by the slave device, it will also issue a command to start the data transmission and receive The data sent from the device finally terminates the receiving process. Emphasize one point: each data transmission is actively started by "MASTER" .

1.8, I2C protocol communication

Insert picture description here
   I2C is a way of communication , so this data transmission process can be understood as a communication in a specific way of communication like I2C. Speaking more popularly, it's just a chat conversation.

  The first step in chatting is to take out your phone and open WeChat. (Corresponding to the START condition, when the levels of the SDA and SCL lines meet a certain condition at the same time, the transmission starts.)

  After opening WeChat, you need to find a contact to chat. We said before that "MASTER" has many "SLAVERS". This step is that "MASTER" chooses to talk to a certain "SLAVER". (Corresponding to ADDRESS.)

  In the third step, "MASTER" determines whether the purpose of this dialogue is to allocate work to "SLAVER" or let "SLAVER" report after finishing the work. (Corresponding to R/W, R means read, W means write, the purpose of controlling this data transmission is whether the Raspberry Pi writes a value to the PCF or the Raspberry Pi reads a value from the PCF.)
You can see that there is Lots of ACKs. ACK means Acknowledge character, which means that the data receiver tells the data transmitter, "received".

  After that is the data transmission, every time a byte of data is transmitted, an ACK will be sent back to confirm the receipt of the data.

5. Main reference materials

Guess you like

Origin blog.csdn.net/qq_41071754/article/details/114689787