i2c Teensy Master Reader w/Audio Shield?

Status
Not open for further replies.

ragemachine

Active member
Hi all,

Have an integration question... I think I have figured it out, but want to get opinions.

I have an ESP8266 connected to a Teensy 3.6 with an Audio Shield on top. The one data connection between the ESP8266 and Teensy is i2c - pins 4+5 on the ESP8266 by default, and 18+19 on the Teensy (which are also connected to the Audio Shield).

Overall flow of program is supposed to be:
1) ESP8266 receives a file play command over wifi connection from external source
2) ESP8266 sends file number byte over i2c to Teensy
3) Teensy/Audio Shield plays file on SD card based on file number received

I think where I went wrong was trying to code the ESP8266 as i2c master and the Teensy as slave. The Teensy expects to be Master in order to send i2c data to the Audio Shield, right?

So if I re-write things such that the ESP8266 is a slave, with the Teensy doing pull requests, that ought to work?

My main question is: Can I put the code for the wire.requestfrom() in my Teensy main loop? Or is the Teensy Audio.h code doing something in the background that might interfere with that?

Thanks
 
Still not working, even as Master Reader...

Other thoughts:

1) The many files inside Audio.h must define SCL and SDA as pins 18 ad 19, so that should be fine...

2) The audio shield contains 2.2kohm pullup resistors to 3.3V. Is that enough? My wire run from the ESP8266 to the Teensy is ~2ft. I also intend to have a short hop (~4in) to an Adafruit Class D amp for i2c volume control.
 
One more:

I'm powering the Teensy and ESP8266 off of 5V (same Traco 5V converter from Adafruit).

The Audio Shield pulls i2c up to 3.3V - do I need a level-shifter to get it to talk to the ESP8266 or other 5V devices?
 
Can you move ESP connect to T_3.6's Wire1 interface on pin38/SCA1 and pin37/SCL1? That would separate it from the Audio shield if those pins are open.

Do you have a second Teensy to set up and test the Master Slave connections with Audio shield and shorter wires? That would be using tested examples to see it function. 2.2K pullups seems to be the good norm for the 3.3V signals and allow higher speeds than higher values. IIRC the Audio use of the i2c is only on startup to configure the Audio board - I'm not sure if after that switching Master to Slave and reconfiguring the i2c Wire works.

If only doing short and small data transfers why not connect over UART Serial? Serial Data transfer is fast and effective between Teensy and ESP as I used it. Serial1 or 2 can easily do 2 (or 3-4) Mbps transfer and short messages would not tax the system FIFO's or Buffer assuring the data would be ready as needed.
 
It should be that all pins on ESP8266 are 3.3V logic - like the T_3.6. If you have anything in the system higher than 3.3V on i2c it may not work and could damage the EPS8266 or the T_3.6 if not shifted.
 
defragster, willing to give that a shot... do you know of an example for how to code a 2nd i2c interface? I would put the ESP8266, Teensy and Class D amp on it...

It's possible I could have damaged the pins. The class D amp has a vi2c input, and I had connected that to 5V. https://www.adafruit.com/product/1752

I'll need to hook up the speakers and see if the Teensy+Audio shield will actually play files - that will at least tell me if I've damaged anything.

Can you help get me started on what I would need to do to define a 2nd i2c bus? Probably commands to set.SDA1, set.SCL1, begin.wire1()?
 
Missed the part where you suggested the serial interface. Have not used that format before... Will have to look. Is there a simple library/example for it? I only need to send a handful of bytes every few hundred ms or so.
 
Look into the Wire examples maybe the i2c_t3 would be better. Both seem to have examples of master/slave. Using Wire1 will use the default i2c[1] pins indicated.
 
Serial is simple byte transfer. On Teensy Serial is USB - but the commands and interface are the same as Serial1 or Serial2. You can demo with Serial to the IDE Serial Monitor to send and receive characters. Any example doing that will work when ported to UART Serial between ESP and Teensy.
 
Thanks for the support.



And one final thought before I go work on this... if I use the i2c_t3 library, would that conflict with use of the Audio library? (If I replace the Wire.h with i2c_t3.h, am I going to run into problems?)


Edit: Regarding my below question... it looks like pretty much everything in control_sgtl5000.cpp uses the "modify" function which reads a value and then writes a new one. If I can control things like "volume(level);" in my code, then the i2c communication between them is fine.
Good news: The audio works... tested with speakers. Is there any function I can call in my code that would test the Teensy to Audio Shield i2c connection? Some function I can call that would request info over that line so I can see if I get a return?
 
Last edited:
Forget what the i2c effects on startup - assume if some examples work all is well.

Indeed with Audio using Wire - it would be easiest to just stick with that to avoid conflicts or other work. But it may have better examples to set your expectations or prove function up front.

Transferring UART Serial messages would be easier though if those pins are open to use.
 
Oh and one easy single test for UART Serial is also pinning RX<>TX on two ports and sending and receiving. You could at will send out Serial2 to Serial1 the command to play clip#x - then on reading that from Serial1 process it and act.
 
Thanks for the support.

And one final thought before I go work on this... if I use the i2c_t3 library, would that conflict with use of the Audio library? (If I replace the Wire.h with i2c_t3.h, am I going to run into problems?)

I think i2c_t3.h uses a different method to change what pins are used than Wire, and if memory serves one or two other functions has a slightly different signature (uint8_t vs. uint16_t or something like that). That means it won't be a simple job.

For simpler programs, there is a method to always use i2c_t3.h by putting in a Wire.h into your Arduino directory that calls i2c_t3.h instead. But that only works if the libraries don't do tricky things.

But the only real solution is to copy the Audio library to into Arduino directory, renaming it to something different, and then manually changing all Wire.h's into i2c_t3.h's, and fixing up the places that have a different syntax. For most people, this is probably too hard. But perhaps you have the skills and the time to make the change.

Note on Serial UART, you have to make sure that you have the same speed on both sides, and that you take care not to send data too fast to overwhelm the reader.
 
Edit: I am going to read through this. https://forum.arduino.cc/index.php?topic=396450

Does serial communication work similarly to i2c?...

Here's what I want to do:
1) Send 8 bytes from ESP8266 (order matters, each byte is a different thing - song file number, volume, wifi channel, wifi connection status, etc)
2) Receive 8 bytes on Teensy, reading one at a time and assigning each byte to the respective variable

With wire.write this was easy - I was able to specify wire.write(array, number of bytes); - does serial communication offer the same functionality?

Or do I have to do something like...
1) Teensy clears serial buffer (SerialX.clear()), then sends some 1-byte serial value to ESP8266 to request 8 bytes, then waits until SerialX.available() == 8
2) ESP8266 sees the serial.available() > 0, and the byte received triggers it to send 8 bytes, one at a time? - Var1 = Serial.write(), Var2 = Serial.write(), etc...
3) Teensy reads each byte into the respective variables, one at a time

Not sure how to preserve data integrity here.
 
i2c is a more involved bus as there are potentially multiple participants on the bus and it uses other hardware and protocols.

Serial uses dedicated hardware and rules - but it is just two senders and receivers on opposite ends of crossed wires -with a common GND and baud rate.

Arduino has lists of commands and simple samples: https://www.arduino.cc/en/Serial/Read

There are others examples in the Arduino or Teensy Tutorials installed. Neither i2c or UART is assured to run very far - depending on environment and such it may take lowered speeds to run at all.
 
I think I got it working - thanks so much for the suggestion, defragster.

I can see text displaying on my TFT (driven by Teensy, displaying Serial bytes from ESP8266). Variables are seemingly going to the right places (7 bytes, 7 variables).

It may be overkill, but I slapped together some ridiculous thing with an 8th byte as a checksum for the prior 7 - I can throw out the whole serial.read() stream and wait for the next loop if the variables don't add up. Never worked with serial, so I have no idea how reliable the data is.

Will see if I run into any other problems along the way. Not bad for my first time using Serial protocol.

Can you check back in from time to time on this thread? I need to get this code working by the end of this week and am in full panic mode. =P
 
As noted Serial is pretty straightforward with just a few commands. If the cabling is working right and the receiver keeps overflow from happening \reading the input fast enough it is very reliable. On Serial1 and Serial2 with healthy FIFO's to capture the data it is low overhead for some chars between interrupt to push to the buffer. In this case knowing the start or stop of a message to sync to each message - and interpreting the checksum should be sufficient if the wiring isn't too long or exposed to noise.

If you post something it is likely somebody will see it - if a problem a sample to see and reproduce the problem gets the best attention.

How long did your wires end up being? What buad rate?
 
It's a ~2ft cable run, and 115200 rate. I have solid 20AWG wires on there right now. Seems stable. I used Serial5 (pin 33+34), chosen arbitrarily.
 
Status
Not open for further replies.
Back
Top