Translate

Showing posts with label i2c. Show all posts
Showing posts with label i2c. Show all posts

Saturday, May 19, 2018

MSP430 - reading a TSL2561

The TSL2561 is a chipset capable to read IR and visible light intensity and is the chipset used in the iRis project.
This article give some suggestions about how to use this sensor.

Saturday, November 14, 2015

Timer for UV box

Ok, here the deal.
The need is to develop a timer, faster, capable to control up to 16 UV fluorescent bulbs.
Up to 2 hours, 1 second precision, display to show the countdown and menu' management, digital encoder for input, pushbuttons/LEDs.

It can be done in thousands ways, but this time I'll try to put it together using Energia and a BIG help from Roberto.

Friday, October 30, 2015

Working on the iRis project

[To be updated !]

A step-by-step guide to work on git for the iRis project.
If you are new on git and github, read this article first.

The iRis project is on github, so if somebody wants to join it, or just follow the progress, can clone the git repo for iRis.

Saturday, August 8, 2015

MSP430 - I2C library

There are many different library out there to handle I2C with the MSP430.
Some of the libraries are also "official", from TI.

I found a nice and simple C library to handle the I2C with USI is on github and apparently is easy to deploy and use.
This article contains some notes about how to deploy and use the library, closing some missing practical information.

Let's start with ... the hardware.

Hardware


The library was originally developed and tested on an MSP430g2452.
It surely can work on any MSP430 family member that has a USI, that's was anyway my initial intent.
I tried to use an MSP430f2013 but in the end I opted to buy some MSP430g2452 because the 2013 doesn't have enough memory (only 2K ROM) to handle protocol and the rest of the code needed for a project.
The MSP430g2452 has 8K ROM.

After choosing the microcontroller, the attention was concentrated on the I/O pin to use.
Note ! Initially I'm experiment using a Launchpad.
The library expects to use the USI pins, i.e. the P1.6 for the SCL and the P1.7 for the SDA.
Apparently there is NO need to bother with the I/O ports to inform the MSP430 that the 2 pins are dedicated to the USI in I2C mode.
Is enough to program the USI control register to do that, and that is taken care in the i2c_init function provided by the library.

Important !!! The P1.6 on the Launchpad is connected to the green LED !
Remove the jumper on that LED in order to have something working !

Software

Compile it


The library presumably is written for IAR or other commercial system.
In order to compile it with Mspgcc few modifications are necessary.


  1. Remove the specific include of the msp430g2452 header from usi_i2c.c
  2. Add the generic include of msp430 in the usi_i2c.h
  3. Remove the include of the stdint.h header from usi_i2c.c and move in the usi_i2c.h
  4. Change the interrupt declaration, from:
    #pragma vector = USI_VECTOR
    __interrupt void USI_TXRX(void)
    {
      switch(__even_in_range(i2c_state,12))

    to

    __attribute__((__interrupt__(USI_VECTOR)))
    void Usi_txrx (void){  switch(__even_in_range(i2c_state,12))
  5. Move the inline function i2c_done() from the header file (usi_i2c.h) into the module (usi_i2c.c) and leave a function prototype for that function in the usi_i2c.h header file
With these modifications I was able to compile the library using mspgcc.

I also fixed a bug that was preventing the library to read more than 8 bit at a time.
In the usi_i2c.c file, in the interrupt function Usi_txrx change the highlighted line :

..................................................................
..................................................................
case I2C_RECEIVED_DATA:       // received data, send ACK/NACK
    *i2c_receive_buffer = USISRL;
    i2c_receive_buffer++;
    USICTL0 |= USIOE;           // SDA = output
    if(i2c_sequence_length > 1) {    
      // If this is not the last byte
      USISRL = 0x00;                // ACK 
..................................................................
..................................................................

with

..................................................................
..................................................................
case I2C_RECEIVED_DATA:       // received data, send ACK/NACK
    *i2c_receive_buffer = USISRL;
    i2c_receive_buffer++;
    USICTL0 |= USIOE;           // SDA = output
    if(i2c_sequence_length > 0) {   // TheFwGuy MOD !!!    
      // If this is not the last byte
      USISRL = 0x00;                // ACK 
..................................................................
..................................................................


Use it


The library has only three "public" functions and act as Master.
Let see how to use it.

i2c_init


The first public function is called i2c_init and like the name imply, is used to initialize the USI and set up the MSP430 to use it.
It must be called once, preferably after other basic I/O initializations happens.
After that, the "system" should be able to send out I2C messages.

Example:

        i2c_init(USIDIV_5, USISSEL_2);

The first parameter determine the division applied to the input clock.
USIDEV_0 divide by 1, USIDEV_1 divide by 2, USIDEV_2 divide by 4 and so on (see MSP430 Family user guide - USICKCTL register).
The second parameter determine the source of the clock (see MSP430 Family user guide - USICKCTL register).
In the example above the source for the clock is the SMCLK divided by 32.

i2c_done


This function returns TRUE (1) or FALSE (0) to indicate if a transaction is running.
The I2C messages are sent via interrupt so it is possible that the main program is ready to send another sequence when the system is still handling the previous sequence.
So before to perform any request, better to see if the system is ready to accept it.
Example:

      if(i2c_done())
         i2c_send_sequence((uint16_t *)seq1, 2, (uint8_t *)recseq, 0);

or
      while(!i2c_done());

Strongly suggested to use it to prevent to start a sequence when another one is still running.

i2c_send_sequence

This is the main function and the most complex to handle.
Simply put, this function can send and receive information via I2C using a "sequence".
The sequence  is a series of word and commands.
i2c_usi.h  defines two commands :
  • I2C_RESTART
  • I2C_READ
The function has these inputs:

  • sequence
    sequence is a pointer to an array containing the I2C operation sequence that should be performed.
    It can include any number of writes, restarts and reads.
    The sequence is composed of uint16_t, not uint8_t elements.
    This is because the need  to support out-of-band signalling of I2C_RESTART and I2C_READ operations, while still passing through 8-bit data.
    The sequence uses the Bus Pirate I2C convention.
    The address must be prepared manually, adding the R/W bit.
    The address is prepared shifting the 7-bit I2C address to the left and add the R/W bit (0 to write, 1 to read).
    The examples above communicate with a device whose I2C address is 0x1c, which shifted left gives 0x38.
    For reads we use 0x39, which is (0x1c<<1)|1.

    So for example, to write at the address 0x39, the sequence would be:

    • 0x39 << 1 = 0x72
    And to read from the address 0x39:
    • (0x39 << 1) | 1 = 0x73
  • sequence length
    sequence_length is the number of sequence elements (not bytes).
    Sequences of arbitrary (well, 32-bit) length are supported.
  • received data
    received_data should point to a buffer that can hold as many bytes as there are I2C_READ operations in the sequence.
    If there are no reads, 0 can be passed, as this parameter will not be used.
  • wake up sr bits
    Used if you want to use the MSP430 in low power mode.

Building sequences


The sequences to send depends strictly to a specific component so there is no a generic suggestion if not to carefully read the datasheet of the component.


Wednesday, December 3, 2014

TeirmiLab - Raspberry Pi prototype



This article describes the building of a TeirmiLab prototype based on a Raspberry Pi B board.
The goal using a Raspberry Pi is to have a machine that can be expanded later.




Shopping list


The idea is to use a traditional LCD display instead a more sophisticate touch screen display.
Mainly the reasons :
  • is not expensive
  • doesn't require to develop a graphic interface for it
  • allows to focus on the purpose - to show a temperature
  • can be easily placed inside a protective container (no touch capabilities)

Hardware


Here a initial schematic for the TeirmiLab-Pi.



The RTC clock module is actually necessary only for the enhanced version, for the data-log feature, however it will be tested also on the base version.
The idea is to use as much as possible "ready to use" modules, like the RGB display, the GPIO I2C expander and so on, in order to use already made code (see the Software section).

The encoder will be connected directly to the Raspberry GPIO as well as the interrupt signal from the MCP23017 (optional for now), in order to be able to detect faster changes from the keyboard.
The internal pullup resistors for the encoder will be enabled.

First tests on a breadboard
The second prototype on perforated board

The second prototype on perforated board
The second prototype with the keyboard and RPOf cable connected
The keyboard is working fine, however it would be better to have an easiest way to select an alarm or set up the offset.
A new version of the hardware will include a digital encoder to be used instead the keyboard (see below).

The prototype installed on a wooden platform for a more mechanical stability.
A monochromatic LCD is used instead an RGB one

The prototype installed on a wooden platform for a more mechanical stability.
The round PCB is hosting the RPOf to be piggy-bagged on a MSP430 Launchpad
The used board for the prototype is a Raspberry Pi B, however the final installation will use a Raspberry Pi A+ because the reduced dimensions and power usage.
A new interface board is under development.

GPIO Use

Here a table for the GPIO use :

Raspberry GPIO MCP GPIO Direction Description

GPA0 Output LCD

GPA1 Output LCD

GPA2 Output LCD

GPA3 Output LCD

GPA4 Output LCD

GPA5 Output LCD

GPA6 Output LCD

GPA7 Output LCD





GPB0 Output LCD

GPB1


GPB2


GPB3


GPB4 Input Keyboard 1

GPB5 Input Keyboard 2

GPB6 Input Keyboard 3

GPB7 Input Keyboard 4




GPIO4
Input/Output 1Wire protocol
GPIO17
Input Shutdown input
GPIO18
Output Shutdown feedback
GPIO22
Output Buzzer
GPIO23
Input Encoder A
GPIO24
Input Encoder B
GPIO25
Input Encoder switch


Sensor


With the sensor used (DS18B20) the TeirmiLab has these basic characteristics:

  • Range -55 to 125°C (-67°F to +257°F)
  • ±0.5°C Accuracy from -10°C to +85°C

Keyboard


The TeirmiLab-Pi needs to have at least 3 push buttons in order to do some settings.
  • a Mode button
    Allows to select different modes, like "display temperature" or "Set alarm" or "Set offset"
  • two + and - buttons
    Allows to increase or decrease a value, like the alarm temperature or the offset

Encoder


Instead of the keyboard, it is more easy to use a mechanical digital encoder with an embedded pushbutton for the selection.
The pushbutton acts as Mode button and rotating the encoder cause the values to change.

The video is showing the encoder operations

Power Supply


The instrument must be powered.
An USB wall wart, with at least 1 A, will be the power source for the Teirmilab.

A main switch will be necessary in order to correctly power up and power down  the instrument (see RPOf project)

Container


All the electronic will be placed in a transparent plastic box.
This will allow to reduce the drilling to the minimum, basically for the main power switch and eventually for some push buttons if not other means are used.
The display will remain totally protected but visible behind the clear plastic.

Saturday, October 11, 2014

Raspberry Pi - connecting a traditional LCD display (Update)

Raspberry Pi is a powerful enough platform and  it is possible to use many recent touchscreen with a nice graphic on it.
However often a traditional LCD is more useful, and surely is more cheap than a touchscreen solution.

Here one way to connect a traditional LCD and use it in projects, like the TeirmiLab one.
This article describes how to connect a traditional LCD but with RGB capabilities to the Raspberry Pi B.

We need :

It is possible to hook a display without the need of the GPIO expander, however a normal LCD uses at least 6 signals. 9 if the LCD display is an RGB one like the one used for this project.
Considering that the Raspberry Pi B doesn't have many GPIO available and that usually the speed required to handle the display is not critical, using a chip like the MCP23017 make sense.
In this way it will be enough to "hook" the  chip to the I2C bus, leaving all the Raspberry Pi GPIO free for other use.

Let see a schematic.


Software


There are many ways to control the hardware.
For now I found a ready-to-use Python library published by Adafruit that is working nicely.
Again, the important thing is that control an LCD is not a critical task, so a python script is Ok.
Maybe in future I'll explore the possibility to control it directly in C.

Python 

To use our display we need to install some code in our Raspberry.
Here a quick step-by-step guide (see Adafruit tutorials for a more detailed and easy instructions) :


  1. sudo apt-get update
  2. sudo apt-get install build-essential python-dev python-smbus python-pip
  3. sudo apt-get install i2c-tools
  4. sudo pip install RPi.GPIO
  5. cd ~
  6. git clone https://github.com/adafruit/Adafruit_Python_CharLCD.git
  7. cd Adafruit_Python_CharLCD
  8. sudo python setup.py install
Before to be able to use it, we need to be sure a configuration file is correctly set-up.

Execute : sudo nano /etc/modules

and if the file exists, add these two lines in the end.

i2c-bcm2708 
i2c-dev

Save the file then open another one in edit.
Execute : sudo nano /etc/modprobe.d/raspi-blacklist.conf

In this file comment out the two lines showed below, adding # at the beginning:

#blacklist spi-bcm2708
#blacklist i2c-bcm2708


Reboot Raspberry : sudo shutdown -r now
or : sudo reboot

At this point everything should be installed in order to use the display.
First is better to run an utility to see if the I2C GPIO expander is seen correctly.

sudo i2cdetect -y 1

The command should display a table and in the table should be present a 0x20 address.

pi@raspberrypi ~ $ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         
pi@raspberrypi ~ $ 


If so, the chip is correctly seen by Raspberry.

To test if the display is working you can execute a test script :
  1. cd Adafruit_Python_CharLCD/examples
  2. sudo ./char_lcd_mcp.py
Some test messages should be displayed on the LCD display.



Troubleshooting

It is possible to have some problems installing the libraries.
Here a couple of tips and resolutions.

apt-get missing


If you start from a fresh installation of Raspbian, especially a lite version, before to start to follow the instructions above, be sure to execute :


  • sudo apt-get update
  • sudo apt-get upgrade
  • sudo apt-get update
It is important because updating the first time, include more repo on apt-get.

python build fail

If during the python building of the library you have this errors :


python ./setup.py build
Downloading https://pypi.python.org/packages/source/s/setuptools/setuptools-3.5.1.zip
Extracting in /tmp/tmpw6UbTx
Traceback (most recent call last):
  File "./setup.py", line 4, in
    use_setuptools()
  File "/home/pi/Adafruit_Python_CharLCD/ez_setup.py", line 128, in use_setuptools
    return _do_download(version, download_base, to_dir, download_delay)
  File "/home/pi/Adafruit_Python_CharLCD/ez_setup.py", line 108, in _do_download
    _build_egg(egg, archive, to_dir)
  File "/home/pi/Adafruit_Python_CharLCD/ez_setup.py", line 57, in _build_egg
    with archive_context(archive_filename):
  File "/usr/lib/python2.7/contextlib.py", line 17, in __enter__
    return self.gen.next()
  File "/home/pi/Adafruit_Python_CharLCD/ez_setup.py", line 88, in archive_context
    with get_zip_class()(filename) as archive:
  File "/usr/lib/python2.7/zipfile.py", line 770, in __init__
    self._RealGetContents()
  File "/usr/lib/python2.7/zipfile.py", line 813, in _RealGetContents
    raise BadZipfile, "File is not a zip file"
zipfile.BadZipfile: File is not a zip file


this happens because for some magic reason :) the python script screw up the download of a zipped file.
In my case the file was setuptools-3.5.1.zip.

Doing an ls -l showed up to be 122 byte big !! Definitively NOT a zip file.
The workaround was quite easy actually.

  • remove the file : sudo rm setuptools-3.5.1.zip
  • manually download the file :
    wget https://pypi.python.org/packages/source/s/setuptools/setuptools-3.5.1.zip 
  • Re-execute the build : sudo python ./setup.py build

Examples


Be aware about the type of kit you are using.
On the examples area there are different examples depending the type of display in use.

To test the basic display, use : char_lcd_mcp.py
To test the kit with RGB display and pushbutton use : char_lcd_plate.py