Created Mon, 13 Feb 2017 18:57:04 +0000 by acm45
Mon, 13 Feb 2017 18:57:04 +0000
Hi,
I've a chipKIT Max32 board and I'm usign the wire library to read/write an IO expander and to drive a display. The firmware work perfectly if I read/write only the IO expander or only the display, as I put all together it works only if I reduce the frequency of display writes, otherwise it get stuck. In my application I can't reduce the frequency as I need to read the IO expander inputs at maximum frequency. I can't find out why this happens, I've only a Wire.begin(), simply seems that the i2c hardware stops working.
Thank you for your support
Regards
Mon, 13 Feb 2017 21:24:04 +0000
Hi there!
How are you rendering your display? All rows in one go, or one row per update? The common thing to do is to do a single row per update, giving a nice even brightness to all rows and keeping timing consistent. May I see the code for your update routine?
Also, for display updates; I would suggest using SPI I/O expanders (faster) or SPI directly in Max32 (even faster) instead of using I2C. I update my DMD (for a pinball) at 20MHZ instead of 100-400KHz which is common for I2C. That's at least 50x faster, and I'm more than certain that your display can update very fast. :)
Thu, 16 Feb 2017 19:48:07 +0000
Hi rasmadrak,
I'm usign Seeedstudio library for the display with page update. I know that there are other SPI I/O expanders, but the board has the i2c to save IO pin of the microcontroller.
include <SeeedOLED.h>
#include <Wire2.h>
// Definition PIN
#define LED1 5
#define LED2 6
#define BLUE_RST 25
#define SELECTOR 73
#define IP_RESET 76
#define PWRD_WIFI 77
#define SCL2 12
#define BUTTON_INT 22
#define LIGHT_SENSOR_INT 3
// Constant definition
#define I2C_IO_EXP_ADDR 0x27
#define I2C_IO_EXP_ADDR_R 0x4F
#define I2C_IO_EXP_ADDR_READ 0x4F
#define I2C_IO_EXP_IODIR 0x00
#define I2C_IO_EXP_IPOL 0x01
#define I2C_IO_EXP_GPINTEN 0x02
#define I2C_IO_EXP_IOCON 0x05
#define I2C_IO_EXP_GPPU 0x06
#define I2C_IO_EXP_GPIO 0x09
#define I2C_IO_EXP_OLAT 0x0A
#define I2C_LCD_ADDRESS 0x78
#define INT_LUCE 0
#define INT_ENC_A 1
#define INT_ENC_B 2
// Analog pin
#define TEMP_OUT 0
#define TEMP_REF 1
float temperature = 0;
const byte IO_EXPANDER_SETUP_IODIR[2] = {I2C_IO_EXP_IODIR, 0x7F};
const byte IO_EXPANDER_SETUP_GPPU[2] = {I2C_IO_EXP_GPPU, 0x80};
const byte IO_EXPANDER_SETUP_INT[2] = {I2C_IO_EXP_GPINTEN, 0x03};
const byte IO_EXPANDER_OUTPUT[2] = {I2C_IO_EXP_OLAT, 0x00};
const byte IO_EXPANDER_READ_INPUT[2] = {I2C_IO_EXP_GPIO , 0x00};
uint32_t result = 0;
byte pulsanti[1]={0};
int test = 0;
bool fail;
int c = 3;
int c_reg = 0;
int cycle_counter = 0;
int luce_counter = 0;
int luce_counter2 = 0;
volatile int led_state = LOW;
volatile int led_state2 = LOW;
void setup() {
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(PWRD_WIFI, OUTPUT);
pinMode(IP_RESET, INPUT);
pinMode(SELECTOR, INPUT);
pinMode(BUTTON_INT, INPUT);
pinMode(LIGHT_SENSOR_INT, INPUT);
// ***************************************
// Setup IO expander
Wire2.begin();
Wire2.beginTransmission(I2C_IO_EXP_ADDR);
Wire2.send(IO_EXPANDER_SETUP_IODIR[0]);
Wire2.send(IO_EXPANDER_SETUP_IODIR[1]);
Wire2.endTransmission();
Wire2.beginTransmission(I2C_IO_EXP_ADDR);
Wire2.send(IO_EXPANDER_OUTPUT[0]);
Wire2.send(IO_EXPANDER_OUTPUT[1]);
Wire2.endTransmission();
Wire2.beginTransmission(I2C_IO_EXP_ADDR);
Wire2.send(IO_EXPANDER_SETUP_GPPU[0]);
Wire2.send(IO_EXPANDER_SETUP_GPPU[1]);
Wire2.endTransmission();
Wire2.beginTransmission(I2C_IO_EXP_ADDR);
Wire2.send(I2C_IO_EXP_IOCON);
Wire2.send(0x00);
Wire2.endTransmission();
Wire2.beginTransmission(I2C_IO_EXP_ADDR);
Wire2.send(IO_EXPANDER_SETUP_INT[0]);
Wire2.send(IO_EXPANDER_SETUP_INT[1]);
Wire2.endTransmission(1);
// ***************************************
// Turn Off wi-fi
digitalWrite(PWRD_WIFI, HIGH);
SeeedOled.init(); //initialze SEEED OLED display
SeeedOled.clearDisplay(); //clear the screen and set start position to top left corner
SeeedOled.setNormalDisplay(); //Set display to normal mode (i.e non-inverse mode)
SeeedOled.setPageMode(); //Set addressing mode to Page Mode
SeeedOled.setTextXY(0,0); //Set the cursor to Xth Page, Yth Column
}
void loop() {
// Read the IO expander only if the BUTTON_INT is low
if (digitalRead(BUTTON_INT) == 0)
{
Wire2.beginTransmission(I2C_IO_EXP_ADDR);
Wire2.send(0x09);
Wire2.requestFrom(I2C_IO_EXP_ADDR,1);
while(Wire2.available()) // slave may send less than requested
{
c = Wire2.receive();
}
if (bitRead(c,1) == 0)
{
Wire2.beginTransmission(I2C_IO_EXP_ADDR);
Wire2.send(IO_EXPANDER_OUTPUT[0]);
Wire2.send(128);
Wire2.endTransmission(1);
}
else
{
Wire2.beginTransmission(I2C_IO_EXP_ADDR);
Wire2.send(IO_EXPANDER_OUTPUT[0]);
Wire2.send(0);
Wire2.endTransmission(1);
}
}
digitalWrite(LED2, led_state);
digitalWrite(LED1, led_state2);
delay(100);
if (c!= c_reg)
{
c_reg = c;
//SeeedOled.clearDisplay(); //clear the screen and set start position to top left corner
// SeeedOled.setNormalDisplay(); //Set display to normal mode (i.e non-inverse mode)
// SeeedOled.setPageMode(); //Set addressing mode to Page Mode
SeeedOled.setTextXY(0,1); //Set the cursor to Xth Page, Yth Column
if (bitRead(c,0) == 0)
{
digitalWrite(LED1, HIGH);
SeeedOled.putString("PB 1 ON "); //Print the String
}
else
{
digitalWrite(LED1, LOW);
SeeedOled.putString("PB 1 OFF "); //Print the String
}
SeeedOled.setTextXY(1,1); //Set the cursor to Xth Page, Yth Column
if (bitRead(c,1) == 0)
{
// digitalWrite(LED2, HIGH);
SeeedOled.putString("PB 2 ON "); //Print the String
}
else
{
//digitalWrite(LED2, LOW);
SeeedOled.putString("PB 2 OFF "); //Print the String
}
}
if (cycle_counter%10 == 0)
{
temperature = analogRead(TEMP_OUT);
temperature = temperature - analogRead(TEMP_REF);
temperature = temperature * 0.488;
SeeedOled.setTextXY(2,1);
SeeedOled.putString("Temp: ");
SeeedOled.putFloat(temperature,1);
SeeedOled.putString(" C");
}
cycle_counter++;
}
I'm using the Wire2 library that use the second i2c port of the chipkit. I can't use the first port as I use it for external interrupts. Form many test seems that the i2c stop working during the display update; as I previously wrote, if I remove the display section no problem at all, same thing if I remove the IO expander section, the display works properly.
Regards
Fri, 17 Feb 2017 10:43:29 +0000
Hi there,
I'm not familiar with the Wire2-library, but one thing that comes to mind: You run beginTransmission() but vary the endTransmission variable from (1) / (). Shouldn't this always be endTransmission()?
Sat, 18 Feb 2017 14:09:32 +0000
Hi,
the wire2 library is the same as wire for the first channel, the EndTransmission parameter has no effect, the issue comes after a while suddenly.
Regards
Wed, 22 Feb 2017 12:29:17 +0000
It sounds like there might be some sync issues that appear after a while. Perhaps the I2C-resistor values are wrong?
Wed, 22 Feb 2017 18:56:55 +0000
I2C-resistors values are 2k7 and are ok, signals are clear. It's something related to the firmware libraries, like a double begin() but I can't find it.
Thu, 23 Feb 2017 13:55:00 +0000
Here's one piece that might cause trouble.
// Read the IO expander only if the BUTTON_INT is low
//...
Wire2.beginTransmission(I2C_IO_EXP_ADDR);
//...
while(Wire2.available()) // slave may send less than requested
{
c = Wire2.receive();
}
if (bitRead(c,1) == 0)
{
Wire2.beginTransmission(I2C_IO_EXP_ADDR); <-- Calls a new beginTransmission before the last request was ended?
//...
}
else
{
Wire2.beginTransmission(I2C_IO_EXP_ADDR); <-- Calls a new beginTransmission before the last request was ended?
//...
}
}
//...
Thu, 23 Feb 2017 21:20:24 +0000
Hi, Thanks for the advice but I've already added the code Wire2.endTransmission(), nothing changed.