Hi Richard,
I' m converting a system for noise measurement from Teensy 3.6 to Teensy 4.0. The system uses the Teensy to read the input from a microphone and calculate the SPL and some more values and than transmits these values over I²C to a master (in my case a NodeMCU - ESP8266 system). The Teensy 3.6 system uses the Wire lib and all works well.
For Teensy 4.0 I found your lib supporting slave mode and tried it. Well I have the problem that there are sporadically errors in the I²C transmission. To catch the problem I used your examples which worked fine. Than I changed the number of transmitted bytes from master to slave and vice versa to 31 bytes. Based on your recommendation not to use the Wire API I switched to the i2c_driver.h API but still getting sporadically errors in the transmission from slave to master.
Any hint what is going wrong is apprtiated.
Code for slave and master follows as well as some pictures showing the errors in transmisson.
Slave:
Master:
Some pictures:
Regards,
Helmut
I' m converting a system for noise measurement from Teensy 3.6 to Teensy 4.0. The system uses the Teensy to read the input from a microphone and calculate the SPL and some more values and than transmits these values over I²C to a master (in my case a NodeMCU - ESP8266 system). The Teensy 3.6 system uses the Wire lib and all works well.
For Teensy 4.0 I found your lib supporting slave mode and tried it. Well I have the problem that there are sporadically errors in the I²C transmission. To catch the problem I used your examples which worked fine. Than I changed the number of transmitted bytes from master to slave and vice versa to 31 bytes. Based on your recommendation not to use the Wire API I switched to the i2c_driver.h API but still getting sporadically errors in the transmission from slave to master.
Any hint what is going wrong is apprtiated.
Code for slave and master follows as well as some pictures showing the errors in transmisson.
Slave:
Code:
// Wire Slave Receiver
// by Nicholas Zambetti <http://www.zambetti.com>
// Modified by Richard Gemmell Oct 2019
// Demonstrates use of the Wire library
// Receives data as an I2C/TWI slave device
// Refer to the "Wire Master Writer" example for use with this
// To use it, connect a master to the Teensy on pins 18 and 19.
//
// Consider using the I2CRegisterSlave class instead of Wire to
// create an I2C slave.
// Created 29 March 2006
// This example code is in the public domain.
#include <Arduino.h>
#include <i2c_driver.h>
#include "imx_rt1060/imx_rt1060_i2c_driver.h"
uint8_t number_bytes;
uint8_t i;
uint8_t ii;
const uint16_t slave_address = 0x0055;
I2CSlave& slave = Slave;
void after_receive(int size);
void before_transmit_isr();
void after_transmit();
const size_t slave_rx_buffer_size = 64;
uint8_t slave_rx_buffer[slave_rx_buffer_size] = {};
volatile size_t slave_bytes_received = 0;
// Set up transmit buffer
const size_t slave_tx_buffer_size = 64;
uint8_t slave_tx_buffer[slave_tx_buffer_size] = {};
// Flags for handling callbacks
volatile bool before_transmit_received = false;
volatile bool after_transmit_received = false;
volatile bool buffer_underflow_detected = false;
int led = LED_BUILTIN;
void setup()
{
pinMode(led, OUTPUT);
digitalWrite(led, LOW);
Serial.begin(115200); // start serial for output
delay(500);
Serial.println(" "); Serial.println("I²C slave mode communication test on Teensy 4.0");
// Configure I2C Slave and Start It
slave.after_receive(after_receive);
slave.set_receive_buffer(slave_rx_buffer, slave_rx_buffer_size);
slave.before_transmit(before_transmit_isr);
slave.after_transmit(after_transmit);
slave.set_transmit_buffer(slave_tx_buffer, slave_tx_buffer_size);
slave.listen(slave_address);
}
void loop()
{
if (slave_bytes_received) {
// now copy to transmit buffer
memcpy(slave_tx_buffer, slave_rx_buffer, slave_bytes_received);
// Serial.print("loop: slave_bytes_received "); Serial.print(slave_bytes_received);
// Serial.print(", last byte transmitted: ");
Serial.println(slave_rx_buffer[30]);
// Clear slave_bytes_received to signal that we're ready for another message
slave_bytes_received = 0;
}
if (before_transmit_received) {
}
}
// Called by the I2C interrupt service routine.
// This method must be as fast as possible.
// Do not perform IO in it.
void after_receive(int size) {
// This is the only time we can guarantee that the
// receive buffer is not changing.
// Copy the content so we can handle it in the main loop.
if (!slave_bytes_received) {
slave_bytes_received = size;
digitalWrite(led, LOW); // briefly flash the LED
}
// else ignore this message because the main loop hasn't
// handled the previous one yet.
}
// Called by an interrupt service routine.
// This function must be _very_ fast. Avoid IO.
void before_transmit_isr() {
before_transmit_received = true;
}
// Called by an interrupt service routine.
// This function must be _very_ fast. Avoid IO.
void after_transmit() {
digitalWrite(led, HIGH); // briefly flash the LED
after_transmit_received = true;
if (slave.has_error()) {
I2CError error = slave.error();
if (error == I2CError::buffer_underflow) {
buffer_underflow_detected = true;
} else {
Serial.println("Unexpected error");
}
}
}
Master:
Code:
#include <Wire.h>
// define pins for I2C for NodeMCU
#define I2C_PIN_SCL D4
#define I2C_PIN_SDA D3
uint8_t i = 0;
uint8_t ii = 0;
byte buf [64] = {0x78, 0x20, 0x69, 0x73, 0x20, 0x78, 0x20, 0x69, 0x73, 0x20, 0x78, 0x20, 0x69, 0x73, 0x20, 0x78, 0x20, 0x69, 0x73, 0x20, 0x78, 0x20, 0x69, 0x73, 0x20, 0x78, 0x20, 0x69, 0x73, 0x20};
byte *buf_zeiger = &buf[0];
uint32_t error_counter = 0;
uint32_t loop_counter = 0;
void setup() {
Wire.begin(I2C_PIN_SDA, I2C_PIN_SCL); // join i2c bus (address optional for master)
Serial.begin(115200); // start serial for output
delay(500);
Serial.println(" "); Serial.println(" "); Serial.println(" ");
Serial.println("I²C communication test runnig");
}
void loop() {
Serial.println(" ");
Serial.print("tx: x is "); Serial.print(i);
Wire.beginTransmission(0x55); // transmit to device 0x55
buf[30] = i;
ii = Wire.write(buf_zeiger, 31); // sends 31 bytes
if (ii == 31) {
// all bytes send
ii = Wire.endTransmission(); // stop transmitting
if (ii != 0) error_counter++;
// Serial.print(", return value of endTransmission: "); Serial.print(ii);
i++;
ii = 0;
Wire.requestFrom(0x55, 31); // request 31 bytes from slave device 0x55
Serial.print(", rx: ");
while (Wire.available()) { // slave may send less than requested
char c = Wire.read(); // receive a byte as character
if (ii < 30) {
Serial.print(c); // print the character
if (c != buf[ii]) error_counter++;
} else {
Serial.print(int(c));
if (c != buf[ii]) error_counter++;
}
ii++;
}
Serial.print(", error_counter: "); Serial.print(error_counter);
if (error_counter != 0) {
Serial.println(" ");
Serial.print("error_counter: "); Serial.print(error_counter);
Serial.print(", loop_counter: "); Serial.print(loop_counter);
while (1) {
delay(100);
}
}
loop_counter++;
// Serial.print(", loop_counter: "); Serial.print(loop_counter);
delay(150);
} else {
// something went wrong
Wire.endTransmission(); // stop transmission an start again
Serial.print(" error, # bytes send: "); Serial.print(ii);
}
}
Some pictures:
Regards,
Helmut