Menu

all about electronic and microcontrollers

Monday, December 31, 2018

PCF8574 [I2C Module] & LCD Display

Overview

The PCF8574 is a silicon CMOS circuit. It provides general purpose remote I/O expansion for most microcontroller families by way of the I2C interface [serial clock (SCL), serial data (SDA)].

The device features an 8-bit quasi-bidirectional I/O port (P0–P7), including latched outputs with high-current drive capability for directly driving LEDs. Each quasi-bidirectional I/O can be used as an input or output without the use of a data-direction control signal. At power on, the I/Os are high. In this mode, only a current source to VCC is active.

This 8-bit input/output (I/O) expander for the two-line bidirectional bus (I2C) is designed for 2.5-V to 6-V VCC operation.


Features
  • Low Standby-Current Consumption of 10 µA Max
  • I2C to Parallel-Port Expander
  • Open-Drain Interrupt Output
  • Compatible With Most Microcontrollers
  • Latched Outputs With High-Current Drive 
  • Capability for Directly Driving LEDs
  • Latch-Up Performance Exceeds 100 mA 
  • Per JESD 78, Class II
  • Package: DIP16, SO16 and SSOP20.
Applications
  • Telecom Shelters: Filter Units
  • Servers
  • Routers (Telecom Switching Equipment)
  • Personal Computers
  • Personal Electronics
  • Industrial Automation
  • Products with GPIO-Limited Processors
Diagram


Pinning


Functional Description


Addressing

We have to pay real attention on this section if we want to communicate with the chip without spending a lot of time to understand why it doesn't work.

In my particular case the chip address, generated by Arduino I2C Scanner, was 1111110x3F and it works well with Arduino Uno board.
The things got messy when I had tried to use the chip with a PIC controller on the regular hardware. I had dug into the issue and I've discovered that string address wasn't complete because it doesn't contained the last state bit (R/W function), which in my case was 0 logic. So the complete string become 1111110 = 0x7E, and the module has revived.


Interrupt output

Interrupts are used when we want to use more than one device via I2C bus.


Application Example

I2C Module for LCD 1602, 1604, 2004 Displays.


Test Example

I have a very good confident into PicKit2 Programmer, that's why often it will be seen into my photos.


Code Example

Written in MikroC Pro for PIC v7.2.0

/************************************************************************
*  Project name: I2C(PCF8574) & LCD1602
*  Description: Communication test
*    Hardware configuration is:
*             IC PCF8574 is connected with our microcontroller by RC3=SCL,
*             RC4=SDA (I2C Connections), +5vdc and circuit ground
*             Message example written on 16x02 LCD characters:
*             ------------------
*             |I2C LCD 16x2    |
*             |PIC16F876A 8 MHz|
*             ------------------
*  Adapted by:
*    Aureliu Raducu Macovei, 2018.
*  Test configuration:
*    MCU:                        PIC16F876A;
*    Test.Board:                 WB-106 Breadboard 2420 dots;
*    SW:                         MikroC PRO for PIC 2018 (version v7.2.0);
*  Configuration Word:
*    Oscillator:                 HS (8Mhz)on pins 9 and 10;
*    Watchdog Timer:             OFF;
*    Power up Timer:             OFF;
*    Browun Out Detect:          ON;
*    Low Voltage Program:        Disabled;
*    Data EE Read Protect:       OFF;
*    Flash Program Write:        Write Protection OFF;
*    Background Debug:           Disabled;
*    Code Protect:               OFF
************************************************************************/
#define _LCD_FIRST_ROW          0x80     //Move cursor to the 1st row
#define _LCD_SECOND_ROW         0xC0     //Move cursor to the 2nd row
#define _LCD_THIRD_ROW          0x94     //Move cursor to the 3rd row
#define _LCD_FOURTH_ROW         0xD4     //Move cursor to the 4th row
#define _LCD_CLEAR              0x01     //Clear display
#define _LCD_RETURN_HOME        0x02     //Return cursor to home position, returns a shifted display to
                                         //its original position. Display data RAM is unaffected.
#define _LCD_CURSOR_OFF         0x0C     //Turn off cursor
#define _LCD_UNDERLINE_ON       0x0E     //Underline cursor on
#define _LCD_BLINK_CURSOR_ON    0x0F     //Blink cursor on
#define _LCD_MOVE_CURSOR_LEFT   0x10     //Move cursor left without changing display data RAM
#define _LCD_MOVE_CURSOR_RIGHT  0x14     //Move cursor right without changing display data RAM
#define _LCD_TURN_ON            0x0C     //Turn Lcd display on
#define _LCD_TURN_OFF           0x08     //Turn Lcd display off
#define _LCD_SHIFT_LEFT         0x18     //Shift display left without changing display data RAM
#define _LCD_SHIFT_RIGHT        0x1E     //Shift display right without changing display data RAM

// LCD Definitions
#define LCD_ADDR 0x7E                    // This is PCF8574 adress. On mine pcb "MH" series the adress is 0x3F or 0x7E

// Lcd constants
char txt1[] = "I2C LCD 16x2";
char txt2[] = "PIC16F876A 8 MHz";

void I2C_LCD_Cmd(char out_char) {

    char hi_n, lo_n;
    char rs = 0x00;

    hi_n = out_char & 0xF0;
    lo_n = (out_char << 4) & 0xF0;

    I2C1_Start();
    I2C1_Is_Idle();
    I2C1_Wr(LCD_ADDR);
    I2C1_Is_Idle();
    I2C1_Wr(hi_n | rs | 0x04 | 0x08);
    I2C1_Is_Idle();
    Delay_us(50);
    I2C1_Wr(hi_n | rs | 0x00 | 0x08);
    I2C1_Is_Idle();
    Delay_us(100);
    I2C1_Wr(lo_n | rs | 0x04 | 0x08);
    I2C1_Is_Idle();
    Delay_us(50);
    I2C1_Wr(lo_n | rs | 0x00 | 0x08);
    I2C1_Is_Idle();
    I2C1_stop();

    if(out_char == 0x01)Delay_ms(2);
}

void I2C_LCD_Chr(char row, char column, char out_char) {

    char hi_n, lo_n;
    char rs = 0x01;

    switch(row){

        case 1:
        I2C_LCD_Cmd(0x80 + (column - 1));
        break;
        case 2:
        I2C_LCD_Cmd(0xC0 + (column - 1));
        break;
        case 3:
        I2C_LCD_Cmd(0x94 + (column - 1));
        break;
        case 4:
        I2C_LCD_Cmd(0xD4 + (column - 1));
        break;
    };

    hi_n = out_char & 0xF0;
    lo_n = (out_char << 4) & 0xF0;

    I2C1_Start();
    I2C1_Is_Idle();
    I2C1_Wr(LCD_ADDR);
    I2C1_Is_Idle();
    I2C1_Wr(hi_n | rs | 0x04 | 0x08);
    I2C1_Is_Idle();
    Delay_us(50);
    I2C1_Wr(hi_n | rs | 0x00 | 0x08);
    I2C1_Is_Idle();
    Delay_us(100);
    I2C1_Wr(lo_n | rs | 0x04 | 0x08);
    I2C1_Is_Idle();
    Delay_us(50);
    I2C1_Wr(lo_n | rs | 0x00 | 0x08);
    I2C1_Is_Idle();
    I2C1_stop();
}

void I2C_LCD_Chr_Cp(char out_char) {

    char hi_n, lo_n;
    char rs = 0x01;

    hi_n = out_char & 0xF0;
    lo_n = (out_char << 4) & 0xF0;

    I2C1_Start();
    I2C1_Is_Idle();
    I2C1_Wr(LCD_ADDR);
    I2C1_Is_Idle();
    I2C1_Wr(hi_n | rs | 0x04 | 0x08);
    I2C1_Is_Idle();
    Delay_us(50);
    I2C1_Wr(hi_n | rs | 0x00 | 0x08);
    I2C1_Is_Idle();
    Delay_us(100);
    I2C1_Wr(lo_n | rs | 0x04 | 0x08);
    I2C1_Is_Idle();
    Delay_us(50);
    I2C1_Wr(lo_n | rs | 0x00 | 0x08);
    I2C1_Is_Idle();
    I2C1_stop();
}

void I2C_LCD_Init() {

    char rs = 0x00;

    I2C1_Start();
    I2C1_Is_Idle();
    I2C1_Wr(LCD_ADDR);
    I2C1_Is_Idle();

    Delay_ms(30);

    I2C1_Wr(0x30 | rs | 0x04 | 0x08);
    I2C1_Is_Idle();
    Delay_us(50);
    I2C1_Wr(0x30 | rs | 0x00 | 0x08);
    I2C1_Is_Idle();

    Delay_ms(10);

    I2C1_Wr(0x30 | rs | 0x04 | 0x08);
    I2C1_Is_Idle();
    Delay_us(50);
    I2C1_Wr(0x30 | rs | 0x00 | 0x08);
    I2C1_Is_Idle();

    Delay_ms(10);

    I2C1_Wr(0x30 | rs | 0x04 | 0x08);
    I2C1_Is_Idle();
    Delay_us(50);
    I2C1_Wr(0x30 | rs | 0x00 | 0x08);
    I2C1_Is_Idle();

    Delay_ms(10);

    I2C1_Wr(0x20 | rs | 0x04 | 0x08);
    I2C1_Is_Idle();
    Delay_us(50);
    I2C1_Wr(0x20 | rs | 0x00 | 0x08);
    I2C1_Is_Idle();
    I2C1_Stop();

    Delay_ms(10);

    I2C_LCD_Cmd(0x28);
    I2C_LCD_Cmd(0x06);
}

void I2C_LCD_Out(char row, char col, char *text) {
    while(*text)
    I2C_LCD_Chr(row, col++, *text++);
}

void I2C_LCD_Out_Cp(char *text) {
    while(*text)
    I2C_LCD_Chr_Cp(*text++);
}

void main() {

    TRISA = 0x00;
    PORTA = 0x00;

    I2C1_Init(100000);

    I2C_LCD_Init();
    I2C_LCD_Cmd(_LCD_CURSOR_OFF);
    I2C_LCD_Cmd(_LCD_CLEAR);
    I2C_Lcd_Out(1,1,txt1);                 // Write text in first row
    I2C_Lcd_Out(2,1,txt2);                 // Write text in second row

    while(1) {

    }
}

Saturday, November 17, 2018

DHT22 & LCD Shield

In this article I will describe to you, how to develop a home weather station using the DHT22 temperature/humidity sensor.

TECHNICAL DETAILS

Model:
Power supply:
DHT22
3.3-6V DC (2.5mA max current use during conversion (while requesting data))
Output signal:
Digital signal via single-bus
Sensing element:
Polymer capacitor
Operating range:
Humidity: 0-100%RH;
Temperature: -40~80Celsius
Accuracy:
Humidity +-2%RH(Max +-5%RH);
Temperature <+-0.5 Celsius
Resolution or sensitivity:
Humidity 0.1%RH;
Temperature 0.1Celsius
Repeatability:
Humidity +-1%RH;
Temperature+-0.2Celsius
Humidity hysteresis:
+-0.3%RH
Long-term Stability:
+-0.5%RH/year
Sensing period:
Average: 2s
Interchangeability:
fully interchangeable
Dimensions:
Small size 14*18*5.5mm;
Big size 22*28*5mm
Weight (just the DHT22):
2.4g

Hardware setup:
The development board used for this experiment will be the Arduino UNO and the measured values will be displayed on 1602 LCD Keypad Shield board.

DHT22 is a low-cost digital temperature and humidity sensor. It uses a capacitive humidity sensor and a thermistor to measure the surrounding air, and generate out a digital signal on the data pin (which means no analog input pins needed). It's fairly simple to use, but requires careful timing to collect data. The only real downside of this sensor is you can only get new data from it once every 2 seconds, so when using DHT22 library, sensor readings can be up to 2 seconds old.

Simply connect the first pin on the left to 3-5V power, the second pin to your data input pin and the rightmost pin to ground. Although it uses a single-wire to send data it is not Dallas One Wire compatible! If you want multiple sensors, each one must have its own data pin.

In my particular case 1602 LCD Keypad Shield ICSP connector (VCC, D11, GND) was the easiest way to connect my DHT22 sensor. Keypad functionality wouldn’t be used on this article.




Some pictures from the surgery.


On below video we can see the Arduino UNO board in action.


Software:
The program is written in Arduino IDE software (version v1.8.7).

Libraries used:

Below is presented the software approach for this project:

/*
'*******************************************************************************
'  Project name: DHT22 & LCD Shield
'  Description:
'   In this experiment i will describe to you, how to develop a home weather 
'   station using the DHT22 temperature/humidity sensor.       
'   Temperature will be displayed in Celsius Degree and the Umidity in percent
'   The delay between two consecutive reads is set to about 2.1 seconds.
'          Ex. of viewing display: 
'               ________________                         
'              |TEMP.: 24.60 C  |     
'              |Humy.: 54.40 %__|
'
'   Hardware configuration is:
'             DHS22 is connected to 1602 LCD Keypad Shield ICSP connector (vdc, d11,gnd).
'             The 1602 LCD Keypad Shield board is inserted into Arduino UNO standard connectors.
'
'  Written by:
'          Aureliu Raducu Macovei, 2018 (www.electronicexperiments.blogspot.com).
'
'  Test configuration:
'    MCU:                        ATmega328P;
'    Test.Board:                 Arduino UNO;
'    SW:                         Arduino IDE software (version v1.8.7);
'                                DHT Library from Arduino official website:
'                                https://playground.arduino.cc/Main/DHTLib
'*******************************************************************************
 */
 
#include LiquidCrystal.h // includes the LiquidCrystal Library
#include DHT22.h         // includes the DHT22 Library

#define DHT22_PIN 11

// Setup a DHT22 instance
DHT22 myDHT22(DHT22_PIN);

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 8, en = 9, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.setCursor(0,0);
  lcd.print("    -DHT22 &-   ");
  lcd.setCursor(0,1);
  lcd.print("  --LCD 2x16--  ");
  delay(5000);
  lcd.setCursor(0,0);
  lcd.print("                ");
  delay(100);
  lcd.setCursor(0,1);
  lcd.print("                ");
  delay(500);
}

void loop(void)
{ 
  DHT22_ERROR_t errorCode;
  // The sensor can only be read from every 1-2s, and requires a minimum
  // 2s warm-up after power-on.
  delay(2100);

  errorCode = myDHT22.readData();
  switch(errorCode)
  {
    case DHT_ERROR_NONE:
      lcd.setCursor(0,0);     // Set the first row (location at which subsequent text written to the LCD will be displayed)
      lcd.print("Temp.: ");   // Print "Temp.:" on the LCD
      lcd.print(myDHT22.getTemperatureC());     // Print string temperature
      lcd.print(" C");                          // Prints "C" on the LCD
      lcd.setCursor(0,1);     // Set the second row (location at which subsequent text written to the LCD will be displayed)
      lcd.print("Humi.: ");   // Print "Humi.:" on the LCD
      lcd.print(myDHT22.getHumidity());         // Print string humidity
      lcd.print(" %");        // Prints "%" on the LCD
      break;
    case DHT_ERROR_CHECKSUM:
      lcd.print("check sum error ");
      lcd.print(myDHT22.getTemperatureC());
      lcd.print("C ");
      lcd.print(myDHT22.getHumidity());
       lcd.println("%");
      break;
    case DHT_BUS_HUNG:
      lcd.println("BUS Hung ");
      break;
    case DHT_ERROR_NOT_PRESENT:
      lcd.println("Not Present ");
      break;
    case DHT_ERROR_ACK_TOO_LONG:
      lcd.println("ACK time out ");
      break;
    case DHT_ERROR_SYNC_TIMEOUT:
      lcd.println("Sync Timeout ");
      break;
    case DHT_ERROR_DATA_TIMEOUT:
      lcd.println("Data Timeout ");
      break;
    case DHT_ERROR_TOOQUICK:
      lcd.println("Polled to quick ");
      break;
  }
}

Arduino Uno (Rev.3) Development Board

Arduino Uno is a development board based on the ATmega328P microcontroller. It has 14 digital input/output pins (of which 6 can be used as PWM outputs), 6 analog inputs, a 16 MHz quartz crystal, a USB connection, a power jack, an ICSP header and a reset button. It contains everything needed to support the microcontroller; simply connect it to a computer with a USB cable or power it with a AC-to-DC adapter or battery to get started.

You can tinker with your UNO without worrying too much about doing something wrong, in worst case scenario you can replace the chip for a few dollars and start over again.

"Uno" means one in Italian and was chosen to mark the release of Arduino Software (IDE) 1.0. The 
Uno board and version 1.0 of Arduino Software (IDE) were the reference versions of Arduino, now evolved to newer releases. The Uno board is the first in a series of USB Arduino boards, and the reference model for the Arduino platform; for an extensive list of current, past or outdated boards see the Arduino index of boards.

Tech Specs:

Microcontroller
Operating Voltage
5V
Input Voltage (recommended)
7-12V
Input Voltage (limit)
6-20V
Digital I/O Pins
14 (of which 6 provide PWM output)
PWM Digital I/O Pins
6
Analog Input Pins
6
DC Current per I/O Pin
20 mA
DC Current for 3.3V Pin
50 mA
Flash Memory
32 KB (ATmega328P) of which 0.5 KB used by bootloader
SRAM
2 KB (ATmega328P)
EEPROM
1 KB (ATmega328P)
Clock Speed
16 MHz
LED_BUILTIN
13
Length
68.6 mm
Width
53.4 mm
Weight
25 g

Schematics:

Schematics.pdf       

For more details please visit the Arduino website.

Wednesday, November 14, 2018

Arduino

Arduino is an Italian open source electronic platform. The keystone of this amazing platform is the easiest way of using the hardware and the software tools (libraries, etc.).
Basically you can create everything you purpose, by sending a set of instructions to the microcontroller on the board. To be able to achieve that, you must use Arduino programming language (based on Wiring), and the Arduino Software (IDE), based on Processing.

Over the years Arduino has proved to be an excellent core for thousands of projects, from everyday objects to complex scientific instruments.

A worldwide community of enthusiasts - students, hobbyists, artists, programmers, and professionals has gathered around this open-source platform, their contributions have addedof accessible knowledge that can be of great help to novices up to an incredible amount and experts alike.

Arduino was born at the Ivrea Interaction Design Institute as an easy tool for fast prototyping, aimed at students without a background in electronics and programming. As soon as it reached a wider community, the Arduino board started changing to adapt to new needs and challenges, differentiating its offer from simple 8-bit boards to products for IoT applications, wearable, 3D printing, and embedded environments.

All Arduino boards are completely open-source, empowering users to build them independently and eventually adapt them to their particular needs. The software, too, is open-source, and it is growing through the contributions of users worldwide.

Arduino also simplifies the process of working with microcontrollers by offering some advantage for teachers, students, and interested amateurs over other systems:
  • Inexpensive Arduino boards are relatively inexpensive compared to other microcontroller platforms. The least expensive version of the Arduino module can be assembled by hand, and even the pre-assembled Arduino modules cost less than 40€.
  • Cross-platform  The Arduino Software (IDE) runs on Windows, Macintosh OSX, and Linux operating systems. Most microcontroller systems are limited to Windows.
  • Simple, clear programming environment - The Arduino Software (IDE) is easy-to-use for beginners, yet flexible enough for advanced users to take advantage of as well. For teachers, it's conveniently based on the Processing programming environment, so students learning to program in that environment will be familiar with how the Arduino IDE works.
  • Open source and extensible software  The Arduino software is published as open source tools, available for extension by experienced programmers. The language can be expanded through C++ libraries, and people wanting to understand the technical details can make the leap from Arduino to the AVR C programming language on which it's based. Similarly, you can add AVR-C code directly into your Arduino programs if you want to.
  • Open source and extensible hardware - The plans of the Arduino boards are published under a Creative Commons license, so experienced circuit designers can make their own version of the module, extending it and improving it. Even relatively inexperienced users can build the breadboard version of the module in order to understand how it works and save money.


How to start with Arduino ?!
If you are looking for inspiration you can find a great variety of Tutorials on Arduino Project Hub.

Enjoy !!!