2

It's not often I ask a question. This one has me a little stumped though.
Scenario:
I have an 328PB (internal 8mhz), it speaks to a multiplexer on Wire1 (the PB's second IC2 - Minicore lib). The multiplexer speaks to many sensors. That is all working just fine.
I have a logic analyser hooked up to the key points so I can see what is going on.
I have a Nano (external 16mhz) hooked up to Wire (the PB's first I2C), it sends a master request.
The PB is master on Wire1 and slave on Wire.
For some reason the Nano's request on (address 8) is acknowledged by the PB but then the subsequent reads deliver a zero byte and an NACK.
I'm just asking for one byte to troubleshoot. Previous attempts at multiple bytes would deliver the expected bytes but all of them zero.
Strange thing I'm seeing on the logic analyser is that the PB to Multiplexer communication seems to be slower than the Nano to PB (much slower).
I've looked through the libraries and both Wire and Wire1 seem to calculate the speed down to 100khz. I'm using the standard Arduino Wire on the Nano. Given that the initial Address comms gets an ACK. I'm stumped why the subsequent read gets zero and a NACK.
Any help to restore my sanity is much appreciated. Chances are I'm having a dumb moment. My suspicions are that the clock differences are to blame (but logically they shouldn't be).


Edit: This is the analyser recording. The dodgy byte is highlighted in Blue. enter image description here

The communication from the Atmega328pb to the multiplexer and then on to the temperature sensor is working fine. Not all of the multiplexer channels have sensors at the moment hence the NACKs but you can see success on channel 1 to the right of the screenshot. The Nano to Atmega328pb communication starts off good but I'm expecting to see 0X41 in the blue box not 0x00.

This is going to end up being something simple, I'm going to kick myself.

Nano code:

#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(9600);             // start serial for output.
}

void loop() {
  Wire.requestFrom(8, 1);         // request 1 byte from slave device #8
  char c = Wire.read();           // receive a byte as character
  Serial.print("The character: ");  
  Serial.println(c);              // print the character
  delay(1000);
}

Atmega328pb requestEvent code:

void requestEvent() {
  Wire.write("A");
}

Edit: There are other wires for programming etc, but they are disconnected during test. Schematic

Edit: I commented out all the usage of Wire1 in the PB code. And the result was that the Nano got it's byte. I wove the usage of Wire1 back into the code. Right up until it was actually active i.e. communicating with the multiplexer. At that point the Nano started getting a zero byte again.

It seems to be when they are both active. Which suggests it is something in the Wire/Wire1 library by Minicore.

I suspect there is something in the registers but scanning the datasheet for the PB is not yielding any insights. Except for this: 26.1 - Device can Operate as Transmitter or Receiver
There is no elaboration in the document that I can see.

I've tried staggering the communication so that neither is active at the same time. Still the same result.

Still hoping that someone here has the answer ;-)

  • Can you draw a picture showing the structure? I've not yet grasped what boards are hooked up to what I2C bus and which role each board has on these busses. Also please show us the code in question – chrisl Sep 30 at 20:21
  • chrisl - thanks for your response, I will draw some diagrams. I'll also post the whole code for each MCU. Many thanks. – Mike Watson Sep 30 at 21:19
  • The 328 is a bare atmega, not an arduino, right? You have to clear the clock divison fuse, otherwise the effective mcu frecuency is 1MHz, not 8MHz. – Sim Son Oct 1 at 12:58
  • @SimSon - Thanks for the pointer. I had the fuse set wrong on the 328PB. Set it to 8Mhz and now the speeds are looking better. Still got my problem though. – Mike Watson Oct 1 at 21:23
  • We'll, a drawing would help us to understand your setup better. – Sim Son Oct 1 at 21:31
0

I got it to work ... sort of. I had to move some lines from init to the loop. I found that by delaying the Wire1 communication (pb to multiplexer) I could get Wire (Nano to pb) to work. Then as soon as the Wire1 communication had finished Wire no longer worked. Interestingly Wire continued to work while Wire1 was also active. This has lead me to believe the end of the Wire1 communication is leaving something in a conflicted state (the events on Wire were not connected any longer). The blunt answer was to re-initialise on each loop. This seems to work but is not particularly elegant.

void loop()
{
    Wire1.begin();
    getTemperatures();
    Wire1.end();
    Wire.begin(8);                                               // Join i2c bus 0 with address #8
    Wire.onReceive(receiveEvent);                                // Register event.
    Wire.onRequest(requestEvent);                                // Register event.
}

I'm going to continue with this and see if it offers an appropriate degree of reliability. I'm still hunting for the root issue though.

0

I've been rebuilding using Atmel Studio. After a long time bringing my C++ skills up to scratch I've managed to get it to work very reliably. I like the greater level of control it brings. I suspect that I was trying to do something in Arduino IDE that cannot be done with the Wire library. I had to effectively rewrite the Atmel Start Slave driver to get it to behave as I expected it to. I have no other experience of using I2C. So I cannot say whether it is the Atmega328pb that is different or not.
I'm going to stick to Atmel Studio for this project, thanks for all the responses.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.