Differenze tra le versioni di "Arduino, ESP and i2c devices"

Da raspibo.
Jump to navigation Jump to search
m
 
(7 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
This project permits to control a remote LCD display connected via an i2c port expander via Wifi.
+
This project permits to list the Id-s of the devices conncted to the I2C bus.
  
 
I have successfully tested this program on an ESP-12 (ESP8266) using the Arduino IDE.
 
I have successfully tested this program on an ESP-12 (ESP8266) using the Arduino IDE.
Riga 7: Riga 7:
 
The hardware "ingredients" needed for this experiments are:
 
The hardware "ingredients" needed for this experiments are:
 
* a ESP8266 (in the example it is a ESP12).
 
* a ESP8266 (in the example it is a ESP12).
* an lcd-plug by jeelabs including the display
+
* some i2c devices (I use several jeelabs' plugs like I/O expander, Lux, pressure, lcd).
 
* A "console cable" (but any USB to TTL converter is okay).
 
* A "console cable" (but any USB to TTL converter is okay).
  
Riga 30: Riga 30:
  
 
Here is the source code.
 
Here is the source code.
 +
 
<source lang=C>
 
<source lang=C>
 
#include <Wire.h>
 
#include <Wire.h>
#include <ESP8266WiFi.h>
 
 
const char *ssid = "ESPap";
 
const char *password = "thereisnospoon";
 
 
WiFiServer server(23);
 
WiFiClient client;
 
 
#define DISP_ADDRESS      (0x24) 
 
#define LCD_MAX_MESSAGE_LENGTH 40
 
#define LCD_DISPLAY_LINES      2 
 
#define HIGH 1
 
#define LOW 0
 
enum {
 
  MCP_IODIR, MCP_IPOL, MCP_GPINTEN, MCP_DEFVAL, MCP_INTCON, MCP_IOCON,
 
  MCP_GPPU, MCP_INTF, MCP_INTCAP, MCP_GPIO, MCP_OLAT
 
};
 
 
// bits 0..3 and D4..D7, the rest is connected as follows
 
#define MCP_BACKLIGHT  0x80
 
#define MCP_ENABLE      0x40
 
#define MCP_OTHER      0x20
 
#define MCP_REGSEL      0x10
 
 
// Commands
 
#define LCD_CLEARDISPLAY 0x01
 
#define LCD_RETURNHOME 0x02
 
#define LCD_ENTRYMODESET 0x04
 
#define LCD_DISPLAYCONTROL 0x08
 
#define LCD_CURSORSHIFT 0x10
 
#define LCD_FUNCTIONSET 0x20
 
#define LCD_SETCGRAMADDR 0x40
 
#define LCD_SETDDRAMADDR 0x80
 
 
// Flags for display entry mode
 
#define LCD_ENTRYRIGHT 0x00
 
#define LCD_ENTRYLEFT 0x02
 
#define LCD_ENTRYSHIFTINCREMENT 0x01
 
#define LCD_ENTRYSHIFTDECREMENT 0x00
 
 
// Flags for display/cursor on/off control
 
#define LCD_DISPLAYON 0x04
 
#define LCD_DISPLAYOFF 0x00
 
#define LCD_CURSORON 0x02
 
#define LCD_CURSOROFF 0x00
 
#define LCD_BLINKON 0x01
 
#define LCD_BLINKOFF 0x00
 
 
// Flags for display/cursor shift
 
#define LCD_DISPLAYMOVE 0x08
 
#define LCD_CURSORMOVE 0x00
 
#define LCD_MOVERIGHT 0x04
 
#define LCD_MOVELEFT 0x00
 
 
// Flags for function set
 
#define LCD_8BITMODE 0x10
 
#define LCD_4BITMODE 0x00
 
#define LCD_2LINE 0x08
 
#define LCD_1LINE 0x00
 
#define LCD_5x10DOTS 0x04
 
#define LCD_5x8DOTS 0x00
 
  
static int file;
+
void setup()
static uint8_t functionset_flags;
 
static uint8_t displaycontrol_flags;
 
static uint8_t entrymodeset_flags;
 
 
 
void setupmcp(void)
 
 
{
 
{
   Wire.beginTransmission(DISP_ADDRESS);
+
   Wire.begin();
  Wire.write((byte)MCP_IODIR);
 
  Wire.write((byte)0);
 
  Wire.endTransmission();
 
}
 
  
void turnoff(void)
+
   Serial.begin(115200);
{
+
   Serial.println("\nI2C Scanner");
  Wire.beginTransmission(DISP_ADDRESS);
 
  Wire.write((byte)MCP_GPIO);
 
   Wire.write((byte)0);
 
   Wire.endTransmission();
 
 
}
 
}
  
void write1byte(unsigned int value)
+
void loop()
{
 
  Wire.beginTransmission(DISP_ADDRESS);
 
  Wire.write((byte)MCP_GPIO);
 
  Wire.write((byte)(value | MCP_BACKLIGHT));
 
  Wire.endTransmission();
 
}
 
 
 
void write4bits(unsigned int value)
 
 
{
 
{
   write1byte(value);
+
   byte error, address;
   delayMicroseconds(2);
+
   int nDevices;
  write1byte(value | MCP_ENABLE);
 
  delayMicroseconds(2);
 
  write1byte(value);
 
  delayMicroseconds(100);
 
}
 
  
void send(unsigned int value, unsigned int mode)
+
   Serial.println("Scanning...");
{
 
   //printf("SEND %x %d\n",value,mode);
 
  if (mode)
 
    mode = MCP_REGSEL;
 
  write4bits((value>>4) | mode);
 
  write4bits((value &0xf) | mode);
 
}
 
  
#define command(v) send((v),LOW);
+
  nDevices = 0;
 +
  for(address = 1; address < 127; address++ )
 +
  {
 +
    // The i2c_scanner uses the return value of
 +
    // the Write.endTransmisstion to see if
 +
    // a device did acknowledge to the address.
 +
    Wire.beginTransmission(address);
 +
    error = Wire.endTransmission();
  
 +
    if (error == 0)
 +
    {
 +
      Serial.print("I2C device found at address 0x");
 +
      if (address<16)
 +
        Serial.print("0");
 +
      Serial.print(address,HEX);
 +
      Serial.println("  !");
  
  void
+
      nDevices++;
lcd_clear (void)
+
    }
{
+
    else if (error==4)
  command (LCD_CLEARDISPLAY);  // Clear display, set cursor position to zero.
+
    {
  delayMicroseconds(2000);   // This command takes a long time.
+
      Serial.print("Unknow error at address 0x");
}
+
      if (address<16)
 
+
        Serial.print("0");
  void
+
      Serial.println(address,HEX);
lcd_home (void)
+
     }
{
 
  // Set cursor position to zero and undo any scrolling that is in effect.
 
  command (LCD_RETURNHOME);
 
  delayMicroseconds(2000);  // This command takes a long time.
 
}
 
 
 
  void
 
lcd_set_cursor_position (uint8_t col, uint8_t row)
 
{
 
  // If given an invalid row number, display on last line.
 
  if ( row >= LCD_DISPLAY_LINES ) {
 
     row = LCD_DISPLAY_LINES - 1;    // We count rows starting from 0.
 
 
   }
 
   }
 +
  if (nDevices == 0)
 +
    Serial.println("No I2C devices found\n");
 +
  else
 +
    Serial.println("done\n");
  
   // Positions of the beginnings of rows in LCD DRAM.
+
   delay(5000);           // wait 5 seconds for next scan
  const int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
 
 
 
  command (LCD_SETDDRAMADDR | (col + row_offsets[row]));
 
 
}
 
}
  
  void
+
</source>
lcd_display_off (void)
 
{
 
  displaycontrol_flags &= ~LCD_DISPLAYON;
 
  command (LCD_DISPLAYCONTROL | displaycontrol_flags);
 
}
 
  
  void
+
=== Testing ===
lcd_display_on (void)
 
{
 
  displaycontrol_flags |= LCD_DISPLAYON;
 
  command (LCD_DISPLAYCONTROL | displaycontrol_flags);
 
}
 
  
  void
+
Load the program on you ESP. Remember that GP00 must be connected to ground at power-up to set the ESP in "flashing mode".
lcd_blinking_cursor_off (void)
 
{
 
  displaycontrol_flags &= ~LCD_BLINKON;
 
  command (LCD_DISPLAYCONTROL | displaycontrol_flags);
 
}
 
  
  void
+
Unplug GP00 otherwise at the next power cycle your ESP will be in "flashing mode" again.
lcd_blinking_cursor_on (void)
+
If GP00 is unconnected, the program is restarted at power up.
{
 
  displaycontrol_flags |= LCD_BLINKON;
 
  command (LCD_DISPLAYCONTROL | displaycontrol_flags);
 
}
 
 
 
 
 
  void
 
lcd_underline_cursor_off (void)
 
{
 
  displaycontrol_flags &= ~LCD_CURSORON;
 
  command (LCD_DISPLAYCONTROL | displaycontrol_flags);
 
}
 
 
 
  void
 
lcd_underline_cursor_on (void)
 
{
 
  displaycontrol_flags |= LCD_CURSORON;
 
  command (LCD_DISPLAYCONTROL | displaycontrol_flags);
 
}
 
 
 
void
 
lcd_scroll_left (void) {
 
  command (LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
 
}
 
 
 
void
 
lcd_scroll_right (void) {
 
  command (LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
 
}
 
 
 
  size_t
 
lcd_write (char value)
 
{
 
  send ((uint8_t) value, HIGH);
 
  return 1;  // Assume success
 
}
 
 
 
  size_t
 
lcd_write_string (const char *buffer)
 
{
 
  size_t size = strlen (buffer);
 
  size_t n = 0;
 
  while ( size-- ) {
 
    n += lcd_write ((uint8_t) (*buffer++));
 
  }
 
 
 
  return n;
 
}
 
 
 
  int
 
lcd_printf (const char *format, ...)
 
{
 
  char message_buffer[LCD_MAX_MESSAGE_LENGTH + 1];
 
 
 
  va_list ap;
 
  va_start (ap, format);
 
  int chars_written
 
    = vsnprintf (message_buffer, LCD_MAX_MESSAGE_LENGTH, format, ap);
 
  va_end (ap);
 
 
 
  lcd_write_string (message_buffer);
 
  
  return chars_written;
+
Use a terminal emulator to "talk' with yout ESP.
}
+
<pre>
 +
screen /dev/ttyUSB0 115200
 +
</pre>
  
void setup() {
+
You'll get the list of i2c devices (each 5 seconds).
  Wire.begin();
 
  delay(1000);
 
  Serial.begin(115200);
 
  Serial.println();
 
  Serial.print("Configuring access point...");
 
  /* You can remove the password parameter if you want the AP to be open. */
 
  WiFi.softAP(ssid, password);
 
  
  IPAddress myIP = WiFi.softAPIP();
+
<pre>
  Serial.print("AP IP address: ");
+
Scanning...
  Serial.println(myIP);
+
I2C device found at address 0x24  !
 +
done
  
  server.begin();
+
Scanning...
  server.setNoDelay(true);
+
I2C device found at address 0x24  !
 +
done
  
  Serial.println("i2s lcd driver\n");
+
Scanning...
 +
I2C device found at address 0x20  !
 +
I2C device found at address 0x24  !
 +
done
  
  setupmcp();
+
Scanning...
  write4bits(0x03);
+
I2C device found at address 0x20  !
  delayMicroseconds(4500);
+
I2C device found at address 0x24  !
  write4bits(0x03);
+
done
  delayMicroseconds(4500);
 
  write4bits(0x03);
 
  delayMicroseconds(150);
 
  write4bits(0x02);
 
  
  functionset_flags = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS;
+
Scanning...
  // Finally, set # lines, font size, etc.
+
I2C device found at address 0x24  !
  command (LCD_FUNCTIONSET | functionset_flags);
+
done
  
  // Turn the display on with no cursor or blinking cursor.
+
Scanning...
  displaycontrol_flags = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
+
No I2C devices found
  command (LCD_DISPLAYCONTROL | displaycontrol_flags);
+
</pre>
 
 
  // Clear display.
 
  lcd_clear ();
 
 
 
  // Initialize to supported text direction (for romance languages).
 
  entrymodeset_flags = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
 
  command (LCD_ENTRYMODESET | entrymodeset_flags);
 
}
 
 
 
#define LCD_MAX_MESSAGE_LENGTH 40
 
#define LCD_DISPLAY_LINES      2 
 
 
 
int nline=0;
 
int nchar=0;
 
char contents[LCD_DISPLAY_LINES][LCD_MAX_MESSAGE_LENGTH+1];
 
void loop()
 
{
 
  if (!client.connected()) {
 
    if (client) client.stop();
 
    if (server.hasClient())
 
      client = server.available();
 
  } else {
 
    int incomingByte = 0;
 
 
 
    if (client.available() > 0) {
 
      incomingByte = client.read();
 
 
 
      if (incomingByte == '\r' || incomingByte == '\n') {
 
        Serial.println();
 
        client.println();
 
        lcd_home ();
 
        lcd_clear ();
 
        lcd_set_cursor_position(0,0);
 
        lcd_printf(contents[0]);
 
        lcd_set_cursor_position(0,1);
 
        lcd_printf(contents[1]);
 
        nline = (nline + 1) % LCD_DISPLAY_LINES;
 
        nchar = 0;
 
      } else if (incomingByte == 5) { //ctrl-E
 
        for (nline=0; nline<LCD_DISPLAY_LINES; nline++)
 
          contents[nline][0]=0;
 
        nchar = nline = 0;
 
        turnoff();
 
      } else if (nchar < LCD_MAX_MESSAGE_LENGTH) {
 
        contents[nline][nchar++]=incomingByte;
 
        contents[nline][nchar]=0;
 
        Serial.print((char)incomingByte);
 
        client.print((char)incomingByte);
 
      }
 
    }
 
    if(Serial.available()){
 
      client.write(Serial.read());
 
      delay(1);
 
    }
 
  }
 
}
 
</source>
 
 
 
=== Testing ===
 
 
 
Load the program on you ESP. Remember that GP00 must be connected to ground at power-up to set the ESP in "flashing mode".
 
 
 
 
 
 
 
Unplug GP00 otherwise at the next power cycle your ESP will be in "flashing mode" again.
 
If GP00 is unconnected, the program is restarted at power up.
 

Versione attuale delle 10:58, 27 giu 2016

This project permits to list the Id-s of the devices conncted to the I2C bus.

I have successfully tested this program on an ESP-12 (ESP8266) using the Arduino IDE.

hardware

The hardware "ingredients" needed for this experiments are:

  • a ESP8266 (in the example it is a ESP12).
  • some i2c devices (I use several jeelabs' plugs like I/O expander, Lux, pressure, lcd).
  • A "console cable" (but any USB to TTL converter is okay).

wiring

i2c: SDA is GP04, SCL is GP05. The pins of jeelabs' lcd plug (this cabling works for all i2c based jeelabs' plugs):

  • P -> +5V or disconnected (unused for lcd-plug)
  • D -> GP04 (SDA)
  • G -> GND
  • + -> +3V3
  • A -> GP05 (SCL)
  • I -> NC (unused for lcd-plug, can be connected to another GPIO for other boards providing useful interrupts).

Console cable: using an Adafruit like cable:

  • Black -> GROUND
  • While -> TXD on ESP
  • Green -> RXD on ESP

DO NOT CONNECT THE RED PIN TO YOUR ESP! The red pin is +5V while ESP need +3V3 so either you have a step-down circuit to convert 5V to 3.3V or you'll need another power source of the right voltage for yout ESP.

Software

Here is the source code.

#include <Wire.h>

void setup()
{
  Wire.begin();

  Serial.begin(115200);
  Serial.println("\nI2C Scanner");
}

void loop()
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknow error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000);           // wait 5 seconds for next scan
}

Testing

Load the program on you ESP. Remember that GP00 must be connected to ground at power-up to set the ESP in "flashing mode".

Unplug GP00 otherwise at the next power cycle your ESP will be in "flashing mode" again. If GP00 is unconnected, the program is restarted at power up.

Use a terminal emulator to "talk' with yout ESP.

screen /dev/ttyUSB0 115200

You'll get the list of i2c devices (each 5 seconds).

Scanning...
I2C device found at address 0x24  !
done

Scanning...
I2C device found at address 0x24  !
done

Scanning...
I2C device found at address 0x20  !
I2C device found at address 0x24  !
done

Scanning...
I2C device found at address 0x20  !
I2C device found at address 0x24  !
done

Scanning...
I2C device found at address 0x24  !
done

Scanning...
No I2C devices found