Generic software preparation

In future, there will be lot more sensors introduced than those you are working with. It will be great if you develop software that is built to use in any of your analog data acquisition projects. Preparing generic software without any errors will reduce developing time in future, and you can rapidly build projects just by adding the working generic software and calling the functions whenever needed.

We know that the MCP3008 is interfaced through the SPI protocol. To use the SPI protocol, we have to install some additional packages on our RasPi. First of all, we need to make our RasPi up to date. Enter these commands to update and upgrade the OS to the latest kernel package. If you haven't performed any update after the fresh installation, then this may take a long time. Once the process is done, restart the RasPi module to perform the normal operations:

sudo apt-get update
sudo apt-get upgrade
sudo reboot

After this process, we have to make the RasPi board ready with the Python development packages that will bring the default static library packages and header files of the standard Python library:

sudo apt-get install python-dev

Once this installation is done, we have to enable the SPI functionality for the RasPi board. Because of its rare use, the SPI port is disabled by default. Therefore, it is listed under the blacklist configuration file under the /etc directory:

sudo nano /etc/modprobe.d/raspi-blacklist.conf

This command will open the configuration file in a nano editor. Find out the spi-bcm2708 line by scrolling down with keyboard. Put the # sign before this line to avoid blacklisting of the SPI port during the startup process. Press Ctrl + X and then press Y, followed by Enter to save the configuration file. After this process, we have to reboot the RasPi again:

sudo reboot

Now, check whether the RasPi Linux kernel has loaded the SPI drivers while booting or not. Enter the following command and check for the SPI drivers in the list:

lsmod

It is always tricky to work with protocols such as SPI unless some handy library helps us. Thanks to doceme for sharing the python-spidev library on GitHub, which provides us with the functionalities to pull and push the data from the SPI port. Create a new folder for your project and download the spidev library:

mkdir mcpgeneric
cd mcpgeneric
wget https://raw.github.com/doceme/py-spidev/master/spidev_module.c
wget https://raw.github.com/doceme/py-spidev/master/setup.py
sudo python setup.py install

Once the installation is done, we are good to go for writing the code for our sensor station. To understand the code, you first need to understand the data to be sent to the MCP3008 in order to get the right data. As mentioned earlier in the introduction of MCP3008, we know that in MCP3008, there are two modes available: the single-ended mode and the differential mode.

Setting up the chip select and clock is taken care of by the spi-dev library, but we need to understand the data transfer operations of MCP3008. How can the IC understand that it has to perform a single-ended or differential-ended function? For that, we need to send a control command from the master, which is our RasPi itself. We need to send a nibble (4-bit) of data to MCP3008 as a command that has to work on a single-ended mode and has to provide data from the x channel. Take a look at the following table and understand that most significant bit of a nibble has to set 1 to work in a single-ended operation:

Single-ended mode (D3)

D2

D1

D0

Channel to read

1

0

0

0

1

1

0

0

1

2

1

0

1

1

3

1

0

1

0

4

1

1

0

1

5

1

1

0

0

6

1

1

1

1

7

1

1

1

0

8

Before initiating the data transfer from the RasPi to MCP3008, we need to set the CS pin low, and it should be kept low throughout the conversion process. Between two conversions, the CS pin must be pulled high for optimum performance. Fortunately, the spi-dev library takes care of this, and we have to focus more on our logic than writing our own library.

There are two functions in the spi-dev library for sending the data to SPI slave devices. One is spi.xfer(), which works on active high chip select. The other function keeps the chip select (CS) low during operation, and makes the CS high between two blocks of transfers. We will use the spi.xfer2() function, since our device works on active low chip selects and requires the CS pin to be made high after each conversion.

The data flow should be like this:

  • Start bit, (1-bit length, State: High)
  • Control bit, (4-bit length: D0 D1 D2 D3)
  • Wait for the data

This is how our data will look once we send the request to read channel 1 over the SPI line:

Generic software preparation

Now, the spi.xfer2([value1, value2, value3]) function sends 3 bytes over an SPI MOSI line and returns the 3 bytes back in an array. Therefore, we have to send the first byte as (00000001)b or (1)d to the SPI slave over the MOSI line. The second byte should be the nibble data of the command to the slave for selecting the channel, which is (1 D3 D2 D1)b or (8+x)d, where x is the channel number. To make this nibble a byte, we will shift the value of (8+x)d by 4 bits. As per the the timing diagram shown earlier, the third byte is not required to be sent. Therefore, we will send the third byte as (00000000)b or (0)d.

Once the command is sent by spi.xfer2(), all we have to wait for is the response from the slave, which is taken care by the spi.xfer2() function itself. It starts sensing the MISO line after sending the commands over the MOSI line. MCP3008 starts sending the 10-bit data through the MISO line and the data is stored in an array of three elements, each of length 8 bits (1 byte). We prepare a function that can be called by passing the value of channel, and get the read data back from the function as a return value. We can write that function in Python as follows:

def readadc(channel):
value = spi.xfer2([1,(8+channel)<<4,0])
read = ((value[1]&3) << 8) + value[2]
return read

The least significant 8 bit is stored in the value[2] element of array and the remaining two bits are stored in the value[1] element. To make all other bits zero, we will perform the AND operation with (00000011)b or (3)d. Let's take an example to better understand the received data:

Received data = 00000000 01000010 01100010

The array stores the data like this: value [0] = 00000000, value [1] = 01000010, value [2] = 01100010.

We are interested in the last two bits of the value [1] element, as the ADC sends 10 bits of data. We perform the AND operation with 3 bits:

01000010 & 00000011 = 00000010

The sixth bit was already a glitch or unwanted data, which is removed by this operation. We have to shift the values left by 8 digits, as it will finally affect the decimal number.

00000010 << 00001000 = (10000000)b = (127)d

Add this shifted value to the value[2] element.

127 + 98 = 225 is the data received from the ADC convertor.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.162.87