Maximum string length on one line with Arduino IDE? - Page 1
Forum section: electronics / general

author: Electro Fan
author_rank: Super Contributor
timestamp: November 09, 2015, 11:54:32 pm
content: Saw this:Wrapping long stringsYou can wrap long strings like this:char myString[] = "This is the first line"" this is the second line"" etcetera";It would indicate that perhaps there is a limit to how may characters can be on string in one line (without a wrap)?If so, what is the limit?Thanks

author: sleemanj
author_rank: Super Contributor
timestamp: November 09, 2015, 11:56:56 pm
content: Quote from: Electro Fan on November 09, 2015, 11:54:32 pmI doubt it. It just makes it more readable (tidier) that way.

author: nuno
author_rank: Frequent Contributor
timestamp: November 10, 2015, 12:00:21 am
content: That is just C/C++ syntax for you to be able to break a string and continue on the next source code line, for reasons such as readability. For example, an HTTP request template string could be stored like thisconst char* req = "GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n";orconst char* req = "GET %s HTTP/1.0\r\n""Host: %s\r\n""Connection: close\r\n""\r\n";These 2 forms are equivalent in terms of the program the compiler generates.There are string size limits, but I think it is more related to the resources on the specific platform (RAM on the target machine) than the compiler.

author: ataradov
author_rank: Super Contributor
timestamp: November 10, 2015, 12:07:42 am
content: And as far as C / C++ goes, standards compliant compiler must be able to compile a program containing up toQuotefor C andQuotefor C++.LE: Arduino uses C++, so the later limits apply.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 10, 2015, 02:03:31 am
content: ThanksNew question:In a wire.write it seems fine to include a character such as:if(c == 'H'){Wire.beginTransmission(5);Wire.write('H');Wire.endTransmission();If instead of a character a string is inserted is there any limit on the length of the string? Such as:if(c == 'H'){Wire.beginTransmission(5);Wire.write("ABCDEFGJIJKLMNOPQRSTUV");Wire.endTransmission();Thanks

author: nuno
author_rank: Frequent Contributor
timestamp: November 10, 2015, 02:30:28 am
content: You'll have to check the Wire library's documentation.

author: Ian.M
author_rank: Super Contributor
timestamp: November 10, 2015, 02:38:21 am
content: +1 for check the docs!A character constant is *NOT* a string, and cannot be substituted for one except if the function is overloaded and has implementations for both parameter types. Google: C++ function overloading

author: westfw
author_rank: Super Contributor
timestamp: November 10, 2015, 02:46:51 am
content: QuoteI would expect any practical limit to be in the IDE/Editor, rather than in the C++ Compiler.(Although, people who write source code with lines exceeding 4000 characters should be shot. You have ";" to terminate logical lines, so you don't need to be ridiculous!)

author: sleemanj
author_rank: Super Contributor
timestamp: November 10, 2015, 03:12:41 am
content: Quote from: Electro Fan on November 10, 2015, 02:03:31 amFrom looking at the header file in 1.6.5 ({path_to}/Arduino/hardware/avr/libraries/Wire/Wire.h) the Wire library does not support the accepting of a C style null-terminated string without a length argument, so the point is moot.However if in some future version it did support sending a C style null-terminated string without a length argument, it would be a very unusual implementation if it had an artificial limit on the sting size - but of course your hardware imposes a practical physical limit, because your memory (both flash and sram) is extremely limited.Wire.h (in 1.6.x {path_to}/Arduino/hardware/avr/libraries/Wire/Wire.h) defines a buffer length of 32 bytes, and it pulls in Print.h's write() implementation for sizes which will effectively fill the buffer and discard the rest.Because of the wire libraries method of sending only a full buffer when the endTransmission() call is made, you are limited to 32 characters (bytes) sending for a single transmission with the Wire library.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 10, 2015, 03:30:04 am
content: ThanksBackground - I'm at the very beginning of Uno (or any) programming.More background - For the moment I'm not trying to program, I'm just trying to create a way to send some text (a string, I guess) from one Uno to another via I2C so I can create a "test pattern" to probe with a scope.So, I found the Uno sketch that showed how to cause one Uno to communicate to another Uno via I2C. The sketch called for entering H and sending a H for High and entering L and sending L for Low. I was able to decode the H and L into ASCII and Binary but I found that monitoring one character wasn't too interesting. So I tried substituting the transmitted H for several characters and discovered what must be programming lesson #1 - the need to enclose a string of characters with " " instead of ' ' for a single character. This worked fine up to a fairly limited number of characters in the string. Which is what started the questions in this thread. So, for now, all I want to do is to add lots of text (hundreds, thousands, 10s of thousands of text characters) to the string so when I hit H I will be able to monitor the long I2C transmission with the scope.Any suggestions (beyond reading the docs - which I am doing but so far I must be reading the wrong ones)?Thanks again

author: sleemanj
author_rank: Super Contributor
timestamp: November 10, 2015, 03:57:10 am
content: The Wire library for the master transmits only a full buffer at a time, the transmission only happens on endTransmission (for the master). The buffer is 32 bytes long as defined in Wire.hWire.write("HELLO WORLD THE QUICK BROWN FOX", 31);instead of your Wire.write('H') should probably work, note double quotes, note the length of the string (31) and note that the length is less than 32.

author: Ian.M
author_rank: Super Contributor
timestamp: November 10, 2015, 04:23:47 am
content: And if you don't have a DSO, to get a stable trace on an analog scope for you to pick through, wrap that in a while(1){ ... } loop, and pulse a spare output pin before calling Wire.write, so you've got a signal that occurs ONCE per transmission block to feed to your scope's trigger input. Once you have a reliable trigger point, even with an old 50MHz 'boatanchor', as long as its got two channels and a delay timebase with a smooth-acting vernier knob, you can pick your way through the data packet bit by bit decoding it with pencil and squared paper.Its all a lot easier with a DSO, as you can do a one-shot capture, and if its a fancy one with a protocol analyser, it can even decode the I2C bytes for you - *IF* you know how to set up that feature.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 10, 2015, 04:43:56 am
content: So, 32 Bytes maximum with wire.write? That would explain what I have been seeing (short strings).I have a DSO and decoding is pretty straight forward.Any suggestions on how to take a different approach than wire.write (adjust the small piece of code that I have so far below) that would enable much longer text strings to be sent via I2C? Thanks//i2c Master Code(UNO)#include <Wire.h>void setup(){Serial.begin(9600);Wire.begin();}void loop(){while(Serial.available()){char c = Serial.read();if(c == 'H'){Wire.beginTransmission(5);Wire.write("ABCDEFGJIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");Wire.endTransmission();}else if(c == 'L'){Wire.beginTransmission(5);Wire.write('L');Wire.endTransmission();}}}----PS, Where in the library does it say 32 Bytes is the max? Thxhttps://www.arduino.cc/en/Reference/Wire

author: sleemanj
author_rank: Super Contributor
timestamp: November 10, 2015, 05:38:26 am
content: The 32 byte buffer is defined in Wire.h where it says #define BUFFER_LENGTH 32YourWire.write("ABCDEFGJIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");"works" because I missed that Wire.h also pulls in the write function from Print.h which defines the write() function for C style null terminated strings, so Wire.write() also supports them, PROVIDED the length is 32 characters or less, any more than 32 characters will be discarded.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 10, 2015, 07:38:20 pm
content: Quote from: sleemanj on November 10, 2015, 05:38:26 amI believe it is 32 characters or less. Any suggestions on how to adjust the code above to use something other than Wire.write - or is there another sketch available (any link?) that would make it relatively easy to send many more (hundreds, thousands, etc) via I2C? Could be from a PC to one Uno, or from a PC for transmission between two Unos. Thanks

author: hans
author_rank: Super Contributor
timestamp: November 10, 2015, 08:07:10 pm
content: String formatted over multiple lines makes sense if you enter newlines in the string (like the HTTP example).Moreover some coding standards impose a maximum of 80 characters wide per line.This is artificial, i.e. not limited by the machine but instead by humans. Ever had a code file that not only requires vertical scrolling, but also horizontal? PITA.Read material

author: Electro Fan
author_rank: Super Contributor
timestamp: November 10, 2015, 08:18:29 pm
content: Quote from: hans on November 10, 2015, 08:07:10 pmHans, yes I get that 80 characters is a typical line length - it makes for good reading by a human. Humans don't like to scroll horizontally, fully agreed.The purpose for this particular project, however, is not to generate human readable code or text. The purpose of the project is to test the capacity of a Logic Analyzer (actually an oscilloscope). So no one will have to "read" the code or the output.All I want to figure out is an easy way to send text from an IDE to an Arduino Uno and from the Arduino Uno out of it's I2C pins (perhaps to another Arduino Uno). I just need a lot of text (tens of thousands of characters) so I can probe the transmission of the characters on the I2C (SDA and SCL) pins. It's just a matter of knowing what statements to use in the IDE so I can cut and paste a few pages of text from War and Peace (or any other text) into the sketch and not hit a character limit during the I2C transmission of the data (the 1s and 0s that comprise ASCII text).Thx, EF

author: DimitriP
author_rank: Super Contributor
timestamp: November 10, 2015, 08:41:58 pm
content: Perhaps I'm missing something too obvious by why can't the "transmission" code be put in a loop so the same "short" string is being transmitted over and over?

author: hans
author_rank: Super Contributor
timestamp: November 10, 2015, 08:44:33 pm
content: If you're testing the instruments functionality, why not send out Hello World! repeatedly?Code:void loop(){Wire.beginTransmission(...);for (int i = 0; i < 250; i++){Wire.write("Hello World!");}Wire.endTransmission();}The Hello World! string is 12 characters, times 250 is 3000 characters of text.I imagine you want to see what happens if you decode the I2C midstream. I know that my Rigol DS1074Z (old firmware nevertheless) can only decode what is on screen, and wont do a good job if the start bit is not on screen or you're far zoomed out.

author: DimitriP
author_rank: Super Contributor
timestamp: November 10, 2015, 08:49:33 pm
content: Quote from: hans on November 10, 2015, 08:44:33 pmMaybe you are missing something obvious tooCan't wait to find out what it is.

author: sleemanj
author_rank: Super Contributor
timestamp: November 10, 2015, 08:50:25 pm
content: Quote from: Electro Fan on November 10, 2015, 08:18:29 pmYou need to learn about loops; for, while, and do-whileYou also seem to not realise how little memory your arduino has, you simply can not handle "10s of thousands" of unique hard coded character sequences. Your simplest solution is just to put your i2c begin-write-end logic in a loop.

author: sleemanj
author_rank: Super Contributor
timestamp: November 10, 2015, 08:52:08 pm
content: Quote from: hans on November 10, 2015, 08:44:33 pmRight idea. Wrong implementation, as I recall the buffer is only sent and emptied on endTransmission, once buffer is full, rest is discarded.In other words, move the begin and end inside the loop also :-)

author: DimitriP
author_rank: Super Contributor
timestamp: November 10, 2015, 09:03:37 pm
content: Quote from: sleemanj on November 10, 2015, 08:52:08 pmI liked your previous advice better:Quote

author: Electro Fan
author_rank: Super Contributor
timestamp: November 10, 2015, 09:20:08 pm
content: Quote from: DimitriP on November 10, 2015, 08:41:58 pmThat is a very fair question. The answer is that by sending the same short transmission over and over it is pretty hard to know which of the transmissions is being decoded and viewed on the oscilloscope. By sending a long text with reasonably unique paragraphs, sentences, and words it is much easier to verify where in the long string a particular set of characters resides. Not only can you use a word processor to search for text location (if need be), but after a few hours of tedious examination you can pretty much know the document and the relative text location by human memory, if not recite it

author: hans
author_rank: Super Contributor
timestamp: November 10, 2015, 09:40:09 pm
content: Quote from: sleemanj on November 10, 2015, 08:52:08 pmOkay, sorry I didn't run the code. I also don't own an Arduino to do so. So yeah.. I basically assumed write() is a completely synchronous operation.If that isn't the case I would quickly discard such a library and instead start bit-banging pins or find/write other I2C routines.

author: DimitriP
author_rank: Super Contributor
timestamp: November 10, 2015, 09:40:09 pm
content: Quote from: Electro Fan on November 10, 2015, 09:20:08 pmA)If you are hell bent on sending WarAndPeace across the wire at 9600 baud, you better get a Pi and be done.B)As for "pretty hard to know which of the transmissions is being decoded and viewed on the oscilloscope.", C'mon now...send the counter value out as well and you'll know the exact group you are looking at.C)As for learning the document as a side effect....see A)I'm pretty happy to conclude that the largest part of the problem you are trying to solve, is not the actual problem, but your solution.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 10, 2015, 09:43:01 pm
content: Quote from: hans on November 10, 2015, 08:44:33 pmExactly. The Rigol scopes do a pretty good job but they have a few quirks as you describe. I have found that if you send data to be dedcoded and immediately scroll around you run the risk of having data that barely moves off the screen disappear. If you use the record feature the review process becomes much more resilient against the scroll off the screen problem. In fact, if you record long strings of text the scope will break the long text into segments and each segment from the beginning of the text to the end can be searched in order. I have one document that spanned 120 segments. For the most part the end of one segment marries to the beginning of the next segment. This first project was done with RS232 from a text editor through a PC serial port. It proved that the Rigol decoder function can work with relatively large data sets. This next project is intended to do the same with I2C - which is why I'mtrying to figure out how to code the Uno. My first test showed what everyone is pointing out (the 32 Byte limitation); initially I thought I was seeing a problem with the scope - but it was my improper use of code with the Uno. So... now I just want to easily cut and paste (not learn to program) a long string into an Arduino sketch. I'm not adverse to learning to code (in fact it's on my list of stuff I'd very much like to learn). Maybe with a few more pointers (and preferably an example sketch that I could cut and paste for this project) I can earn some coding basics here. (I have already learned one - wire.write is limited to 32 Bytes.)

author: Electro Fan
author_rank: Super Contributor
timestamp: November 10, 2015, 09:53:23 pm
content: Quote from: DimitriP on November 10, 2015, 09:40:09 pmOk, whatever you sayOf course it doesn't have to be War and Peace - any document that will help push the limits and identify the capacity of the scope's decoder memory will do (I realize code is pretty literal, sometimes coding by coders might benefit from interpretation)I like the idea of a counter - trouble is that is something I couldn't have asked about since I hadn't thought of it, but now that you mention it, how would that work? I know, read the documentation and figure it out.As an aside, I think there is a kind of disposition (I won't say attitude) that sometimes comes up with some programmers who say - well, just read the documentation and/or just figure it out. An alternative view is that one of the beauties of the Arduino is the ability to cut and paste. In addition to giving some more immediate results it also allows newbies to then tinker a line at a time to see what causes what - while still having the benefit of some working code that is just an undo away.I do get the fact that some folks have the gift to just get software, and that's cool. But the ability to spoon feed it with Arduino sketches is potentially powerful. I just think the intermediate and advanced users should maybe be a little more inclined to leverage existing sketches as opposed to taking the position that sketch reuse is meaningless or harmful. Just sayin'PS, I didn't say I want to send War and Peace; if you read the post it says "cut and pastea few pagesof text from War and Peace (or any other text)"PSS, the counter idea really is a great idea

author: Electro Fan
author_rank: Super Contributor
timestamp: November 11, 2015, 05:49:06 pm
content: To get back on track / stay on track, the objective is:To figure out how to code an Arduino IDE sketch that would allow many (thousands or tens of thousands of characters) to be transmitted from a Master Uno to a Slave Uno via I2C. The current wire.write approach that I am using seems to be limited to 32 Bytes, so I'm looking for a work around if possible, or if need be a different better approach.The current approach is shown here:]https://www.youtube.com/watch?v=Jndb2vpAWwUIf this could be modified to accommodate longer transmissions, that would be A-OK - seems like there should be an easy way to get around the 32 Byte wire.write limit.In doing some research (as part of "reading the documents"), I found the web post below. Don't know if this could be part of the solution - but any help would be appreciated.An ideal winner would be a link to a sketch that would allow a bunch of text to be inserted and transmitted from an Uno Master to an Uno Slave using I2C.Alternatively, a clear-cut modification of the sketch shown in the video would be fine. Just looking for something clear and understandable for an Arduino beginner.ThxTwo other thoughts: 1) is there a limit specified by I2C regarding how many characters can be transmitted/received? 2) Unless there is an I2C limit it would seem that next limit would be the memory capacity of the an Arduino Uno, correct? Thx again---Re: Send string using i2c#3Apr 22, 2015, 10:49 pmFor future humans reading this who are having this issue but still don't understand why PaulS is saying that Strings aren't strings, here is a more verbose explanation:Arduino nomenclature uses the word "string" (little s) as a shorthand method of denoting an array of chars. This is distinctly different from the class "String" (big S).http://www.arduino.cc/en/Reference/String(it really doesn't help that the URL uses big S...)http://www.arduino.cc/en/Reference/StringObjectHumans who use phonetic pronunciations to derive meaning (or machines that have the ignoreCase flag set) might not understand at first that these two things are very different. You can concatenate a String very easily with concat(). You can not do the same operation with a string. Functions that say they want a string input actually want a char array input, and will get very fussy if you try to give them a String.The main point of confusion (for me, at least) came from the Wire.write() doc page:http://www.arduino.cc/en/Reference/WireWriteIt very clearly states that you can send a string using this function. This, however, does NOT mean that you can send a String (believe me, I've tried - you get about a thousand lines of error messages).So, the solution to this is to convert your String to a string, like so:Code: Big_S_String.toCharArray(little_s_string,;Wire.write(little_s_string);I would personally love it if they changed the documentation to say "char array" instead of "string", since it is not intuitively obvious when first starting out down with an Arduino.As a side note, I'm replying to this year old topic since it was the most relevant to the issue I was facing in hopes that other people who have the same problem and stumble across this thread will understand why their Wire.write() function isn't working. Izak, I hope you've figured all of this out by now.

author: Ian.M
author_rank: Super Contributor
timestamp: November 11, 2015, 06:29:50 pm
content: There is no limit in the I2C protocol: If you have a device that can accept it (e.g. thePCF85748 bit 'dumb' I/O expander), you can stream data to it all day at its max. clock speed.There is no limit in the MCU hardware: I2C master peripherals (in general) send the bytes given to them, receive the Ack bits and only add Start, Stop and Restart framing when commanded to. Bitbanged I2C is only limited by the program writer!There is no practical limit in the amount of data available to send: An I2C bus can be clocked at frequencies right down to DC, so can easily be paused between bytes while the MCU goes off to fetch another sector of data from SD card or other mass storage.The limits you are hitting will be in the 'wire' library, or one of its dependencies, and they are only there because the library was written to be block oriented. You need to get at the raw byte level I2C bus handling primitives so you control the byte flow.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 11, 2015, 08:52:36 pm
content: Quote from: Ian.M on November 11, 2015, 06:29:50 pmThat's all good news - Thanks.So, given that it's doable, I just need to figure out "how"? Seems like there should be an example sketch out there somewhere of a couple Uno's talking to each other Master to Slave that are coded to send long text strings. If anyone sees one, please post it. If there is no such thing it could be a chance for someone to be the first to publish such a sketch

author: westfw
author_rank: Super Contributor
timestamp: November 12, 2015, 07:24:09 am
content: QuoteYou could, you know, just NOT use the Arduino "Wire" library. It seems to be heavily (and not very well) tuned to allowing multiple I2C devices to be used "simultaneously", even if transmits are initiated in ISRs, and using interrupts for the actual transmission as well. If you don't need that, it should be pretty simple to write your own "bare metal" i2c code, following one of the non-arduino AVR examples (say:http://www.ermicro.com/blog/?p=744?)Alternately, you can just break your data into <32byte chunks:Code:i2c_bigwrite(const char PROGMEM *bigdata, int length) {char shortbuf; // nothing like another layer of buffering.while (length > 0) {Wire.beginTransmission();memcpy_P(shortbuf, bigdata, 16);Wire.write(shortbuf, 16);Wire.endTransmission();p += 16;length -= 16;}}

author: amyk
author_rank: Super Contributor
timestamp: November 12, 2015, 09:11:14 am
content: Quote from: westfw on November 12, 2015, 07:24:09 am+1 to this. 32-byte limitationthat is not even mentionedin what appears to be the official documentation?If the function is just sending a null-terminated string it should be able to keep going until it hits the terminator, not at some arbitrary 32 bytes limit!I've had people ask me why I don't use Arduino, "because it's so much easier"...

author: westfw
author_rank: Super Contributor
timestamp: November 12, 2015, 09:32:59 am
content: I'm inclined to agree. The multiple-device capability I was thinking was there doesn't seem to actually exist, either. :-((although, it is non-blocking...)OTOH, it's amazing how long this library has been in use without anyone noticing the (undocumented) limitations.

author: Ian.M
author_rank: Super Contributor
timestamp: November 12, 2015, 10:09:29 am
content: What do you expect of a whole ecosystem designed to encourage cargo-cult programming by the great unwashed? Any sane embedded developer takes a look at the supplied library source (and if there is no source available, either runs screaming for the hills or gives that library + any other tools that demand it a loooooooooooong drop kick), and when the library's code stench is too vile, bites the bullet, grabs the MCU and peripheral chip datasheets and rolls their own. Unfortunately Arduinoland suffers from Sturgeons law to a greater extent than most other platforms, tacking on a second or third coprological '9', and the fractional percentage of $paid$ developers only scrutinise the most odious code turds that have floated to the top of their project cesspool.<dons Nomex suit>

author: obiwanjacobi
author_rank: Super Contributor
timestamp: November 12, 2015, 10:17:36 am
content: In general I would opt for using a library in the assumption that code is tested and used by many others and should not suffer from the bugs you own code may have... Was-Not-Invented-Here is something to be mindful of.

author: Ian.M
author_rank: Super Contributor
timestamp: November 12, 2015, 10:32:10 am
content: Unfortunately, far far too many libraries with published source make you go "W.T.F? Was this the proverbial crack-smoking intern's summer project?". If you use a low cost or free library, you'd better scrutinise it carefully, because you are usually being paid to code the application, not to become a major contributor to an open source or 3rd party project on your employer's dollar.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 13, 2015, 02:40:02 am
content: Quote from: obiwanjacobi on November 12, 2015, 10:17:36 amAnything you might recommend as an alternative relatively easy Uno sketch that would communicate large numbers of Bytes via I2C? Thx

author: westfw
author_rank: Super Contributor
timestamp: November 13, 2015, 03:39:06 am
content: QuoteWhereas libraries with unpublished source code avoid that only by ... not letting you see the soucre code...QuoteIf you use an expensive, proprietary, library, you had better scrutinize it carefully and test the hell out of it. But in that case, you probably have the resources to do so. (actually, I was pretty happy with the only expensive proprietary library that I "bought" and was intimately acquainted with.)(There's nothing quite like the disappointment of being let down by code that you were sure you could trust. The nice thing about poor open source and vendor libraries that that you never quite reach the point of trusting them :-))QuoteDo you actually need a "very large" single I2C transaction? How big, exactly? Do you have a receiver in mind that can receive the data without NAKing? Or do you need a receiver implementation as well? It looks like you can prevent the "Stop" from being sent in endTransmission(), which should give you the same effect as one long packet even though you're calling beginTransmission() multiple times. How many more clues do you want, or do you just want someone to write the code for you so that you can focus on ?analyzing the bitstream on OtherDevice? or whatever?

author: Ian.M
author_rank: Super Contributor
timestamp: November 13, 2015, 04:01:57 am
content: Quote from: westfw on November 13, 2015, 03:39:06 amYes. That's where "....(and if there is no source available, either runs screaming for the hills or give that library + any other tools that demand it a loooooooooooong drop kick)...." comes into play.QuoteOf course, if you've paid for the library, there is an expectation that (paid) support will also be available. I have paid for a source code licence for bundled libraries just because I didn't trust an apparently working binary blob, and wanted to be able to be certain the bugs were in my code not the library. I've also developed a binary patch for an annoying range checking bug in a closed source library@O.P. Stop worshipping John Frum and take look at the wire library's I2C primitives (twi.c) and the processor datasheet to find out what's actually going on 'under the hood'. Also get a PCF8574 chip, to use as a reciever for testing rather than another Arduino. Its just about the dumbest I2C device on the market and you can stream data to it indefinitely. You need each byte ACKed promptly to get low jitter streaming to work, and trying to debug the master end without a bug-free slave is a recipe for frustration.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 13, 2015, 07:30:58 am
content: Quote from: westfw on November 13, 2015, 03:39:06 amPreface: I used (ie, cut and pasted) the sketch shown in the video previously linked into this thread. I did not write the sketch but in the process of using it I discovered that wire.write has a 32 Byte limitation that is perhaps not so well documented. I wrote a post asking for suggestions on how to get around the 32 Byte limitation. To be clear, I did not ask for any "clues". As explained multiple times, I don't have much experience with either I2C or Arduino code. And btw in case it's not clear yet, I don't want "clues".Now to try to answer your questions: Yes, making a relatively large single transaction (transmission) is the objective (I get what an Ack and Nak are, but I have no idea how to get two Unos to manage Acks and Naks). If the code will run by preventing the "Stop", that's swell. I don't care - I'm just trying to make Bytes move via I2C from one Uno to another.As previously mentioned in this this thread, the objective is to be able to transmit thousands of Bytes. So, let's say 40k Bytes plus or minus. (I can of course insert the 40k Bytes - I'm not that clueless, so no need for anyone to do that.)To be clear, the preference, if possible, would be to send the Bytes from one Uno as the master to the second Uno as the slave - so yes, that would take code for the slave Uno to go with code for the master Uno - perhaps along the lines of the sketch shown in the video posted earlier in this thread but without the 32 Byte limitation of wire.write.Yes, I just want to use the code to make the I2C transmissions between the Unos so as to have a testbed which in turn will enable me to focus on better learning the operation and better understand the performance of an oscilloscope's logic analyzer functions. If anyone has ever seen an education demo board, that is sort of what I am looking to establish with this project. I don't really want to code the demo board, but if I had a sketch (or really clear clue-free instructions on how write the code) then I could load the code onto a couple Unos, and that would be great. If in the process, I learn some Uno coding that's A-OK, but it's not the number one objective for this project.So yes, if someone wanted to write the code I would not be too proud too use it. (Although, if it took more than 5 or 10 minutes or about the time it takes to read and write these posts, I'd say forget it unless you enjoy doing such coding.)I realize Arduino is not everyone's first choice but Unos happen to be something I have available and I'd like to use them if possible. So if you or someone knows of such a master/slave I2C sketch on the web and you can post a link to the sketch would be great, or if you or someone wanted to write such a sketch, cool. If not, no worries.

author: obiwanjacobi
author_rank: Super Contributor
timestamp: November 13, 2015, 07:44:11 am
content: Quote from: Electro Fan on November 13, 2015, 02:40:02 amWell, besides the undocumented 'feature' of the internal 32 byte buffer, the code does work. So just do what was suggested earlier and send the large message in chunks.If you're not getting the speed you're looking for, you may want to read up on the USART registers of the 328, specifically the synchronous part... I don't believe that Arduino has any support for that..? (not sure).

author: Electro Fan
author_rank: Super Contributor
timestamp: November 13, 2015, 07:58:04 am
content: Quote from: obiwanjacobi on November 13, 2015, 07:44:11 amEh, Ok, but the clues aren't helping the cluelessWhen you say send the large message in chunks, does that mean chunks that are less than 32 Bytes? Or are you suggesting a method by which the chunks can be larger than 32 Bytes (presumably by not using wire.write)? How about a few lines of example code showing how the chunk method would look within the otherwise working master sketch? Thanks

author: amyk
author_rank: Super Contributor
timestamp: November 13, 2015, 07:59:13 am
content: Quote from: obiwanjacobi on November 12, 2015, 10:17:36 am"tested and used", but which parts? Something like Arduino is not going to be subject to the same sort of thorough use as e.g. the GNU C Library, so it's a mess of code that's just barely working.ST's is no better, when you can find a bug just from a few minutes of actuallyreadingthe source.NIH is just a poor excuse for accepting and using sub-optimal solutions. ("If people didn't reinvent the wheel, we'd still be using ones made of stone.")Get the datasheet and give it a good read. Setting up the peripheral directly to do the appropriate transfers is not hard.Arduino is a tool like any other. As others have alluded to here, you are not obligated to use it for any reason. Use it to make things easier, but when it makes things harder, you should move on to find a better solution.

author: westfw
author_rank: Super Contributor
timestamp: November 13, 2015, 08:29:40 am
content: QuoteI want to see that. Given that the Uno only has 32k of flash... :-)I must be missing something.Wouldn't it be better to exercise the scope's logic-analyzer functions on a scenario that is likely to actually occur in the real world?Something like writing waveform data to an I2C A2D converter, or continuously reading navigation data from a 9DoF sensor board?The Arduino library continues to exist in its relatively broken form, because 99% of the things that people do with it don't hit the broken part...(I found some large I2C EEPROMs that could use an I2C transaction of ~128 bytes, but ... 40k?)

author: obiwanjacobi
author_rank: Super Contributor
timestamp: November 13, 2015, 11:21:13 am
content: @Electro Fan: if you have a buffer of 32 bytes doesn't it makes sense to take chunk of 32 bytes??As to the stability and quality of libraries... Yeah, I'm not going there.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 14, 2015, 12:30:28 am
content: Quote from: obiwanjacobi on November 13, 2015, 11:21:13 amIf I understand - the suggestion is to break 40k Bytes into chunks that are 32 Bytes or shorter?I suppose this is doable, but I see a couple challenges with this approach. One challenge is to write 1000 lines of code. Another challenge is to have some way to navigate the "chunks" so that I know what I am looking at when viewing the monitored transmission.This leads to the earlier idea of a counter or some time of incremented/numbered approach. Conceptually, I can get my head around this: a thousand or so lines numbered 1 thru 1000. Unfortunately, without better coding skills I can't see how to automate this, so it seems like a lot of labor. (But maybe it's a good time learn how to make incrementally numbered lines - I realize it's simple, if you know how.) Alternatively, if I could get past the 32 Byte limitation (still looking for a way to do that) I could cut and past "War and Peace" (it's a joke, it's just an example) or any other several pages of text with a familiar "story" that would enable me to navigate by context when monitoring the transmissions.So far I'm kind of hung up on the fact that 40k / 32 is over a thousand lines of code - it would be a lot easier to paste in 40k Bytes in one big chunk....Thx

author: Electro Fan
author_rank: Super Contributor
timestamp: November 14, 2015, 12:35:32 am
content: Quote from: westfw on November 13, 2015, 08:29:40 amGood point now that you mention it. Previously, before the 32 Byte wire.write limit was surfaced, I asked if there was possibly a limit with the Uno and someone said no - but I think you are right about the 32k limit. So I guess that is the ceiling. The job just got about 20% easier

author: Electro Fan
author_rank: Super Contributor
timestamp: November 14, 2015, 02:42:17 am
content: I guess sending long strings between Arduinos with I2C is too difficult for anyone on this thread to make happen.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 14, 2015, 03:25:12 am
content: Thanks for all the help - yeah right.Turns out I've got 128 Bytes running. Just keeping all the clue providers and cynics postedMake that 512 BytesMake that 1024 Bytes sent from an Uno Master to an Uno Slave via I2C

author: DimitriP
author_rank: Super Contributor
timestamp: November 14, 2015, 03:48:57 am
content: Quote from: Electro Fan on November 14, 2015, 02:42:17 amhttps://en.wiktionary.org/wiki/how_long_is_a_piece_of_string

author: DimitriP
author_rank: Super Contributor
timestamp: November 14, 2015, 03:51:07 am
content: Quote from: Electro Fan on November 14, 2015, 03:25:12 amYou make sure you let us know when you reach you adamant goal of "hundreds of thousands of characters" you specified oh... sooooo many times in earlier posts.Good luck

author: Electro Fan
author_rank: Super Contributor
timestamp: November 14, 2015, 04:05:29 am
content: Quote from: DimitriP on November 14, 2015, 03:51:07 amUp to 1984, hit some wall just before 2048.Obviously if the Uno only holds 32k it will be tough to hit hundreds of thousands of characters but if you read the thread hundreds of thousands was never specified as the goal. Nowhere did I say hundreds of thousands. I said hundreds and thousands and I said tens of thousands and I said 40k (before I recognized the Uno's capacity threshold which is apparently 32k). But you can twist it around any way you want because anyone who posts Donald Trump videos and is a fan of his knows one of his favorite sayings is "Loser".Find one post in this thread where I said "hundreds of thousands". You claim I said it "sooooo many times in earlier posts." You can't find one. And you might not be able to code real well if you can't read. Loser.

author: Ian.M
author_rank: Super Contributor
timestamp: November 14, 2015, 04:14:25 am
content: Its not the difficulty, its the reward:effort ratio. Nobody is paying us to delouse the wire library, and the kudos involved is too insignificant to make anyone inclined to set up to do so for free. To put it bluntly, we don't have skin in the game.Most of us know that transferring large chunks of data by I2C is slow, e.g. 32K will take just under 370ms at the original max clock rate of 100KHz and just over 92ms if its possible to use 400KHz fast mode. That's nearly *forever* in embedded terms. OTOH 1Mbit/s SPI is relatively easy to do and, depending on the MCU, 10Mbit/s may be within reach, and it doesn't have that extra 12.5% overhead due to the Ack bit. Also non-volatile I2C memory tops out around 256Kbytes (2Mbit) but, as standard SD cards have an SPI interface, one can access gigabytes of storage over a SPI bus.I think the longest I2C transfer most of us will have done 'in anger' s 259 bytes as even 2Mbit EEPROMs like ST's M24M02, only have a 256 byte page size for writes and its usually convenient to keep the read and write code using the same size buffers. However sequential reads can access the whole memory, as I did some 15 years ago when I was extending a PIC programmer to handle I2C EEPROMs.Your scope's logic analyser doesn't care whether the I2C stream is coming from a master or a slave, so your easiest way of achieving a continuous stream of a 32K chunk from 'War and Peace' is to extract it, use a utility like BIN2HEX to convert iit to IntelHEX format, burn that to a 24C256 or compatible I2C EEPROM using whatever programmer you can lay your hands on, then write code to bit-bang the start condition, control byte and a memory address of 0x0000 followed by a restart and then set up two PWM modules, one to clock SCL, and the other to pull SDA low every 9th SCL pulse, and you can stream your chunk of Tolstoy 160 times a minute from now to TEOTWAWKI..

author: Electro Fan
author_rank: Super Contributor
timestamp: November 14, 2015, 04:52:47 am
content: Quote from: Ian.M on November 14, 2015, 04:14:25 amI hear you about the reward:effort ratio. But come on man, it's a forum. People come here to learn and help each other not just get rewarded. If you don't want to help someone find solutions, just say in the post "I know, but I'm not incented to tell you." Why tease people?Quote from: Ian.M on November 14, 2015, 04:14:25 amAll of that is interesting regarding projects you are doing or have done but it has next to nothing to do with the project I posted about. Again, why not just make a post that says "Man, I am so far past you I've lapped you." Might not be tremendously helpful, but at least we'd get to your real thinking a little sooner.Quote from: Ian.M on November 14, 2015, 04:14:25 amThat's also interesting, and I'm happy to report that at 1984 Bytes I've exceeded the 259 Bytes (with a capital B) that is "the longest I2C transfer most of us have done 'in anger'". Your 259 bytes (sic) worked for your project - and you had a reason to not want to transfer any more Bytes, that's really neat - but it wasn't what I was solving for. Different horses for different courses.Quote from: Ian.M on November 14, 2015, 04:14:25 amYou might think what you described just above was the easiest way, but you were keeping it pretty close to the vest until now. In the meantime, I found what I think was a still easier way:Wire.beginTransmission(5);Wire.write("Help This Scope Operate 12345001");Wire.endTransmission();Wire.beginTransmission(5);Wire.write("ABCD EFG HIJK LMNOPQR STUVW002");Wire.endTransmission();Wire.beginTransmission(5);Wire.write("Help This Scope Operate 12345003");Wire.endTransmission();Wire.beginTransmission(5);Wire.write("ABCD EFG HIJK LMNOPQR STUVW004");Wire.endTransmission();and so on and so forth .... up to 062 x 32 characters including spaces = 1984 Bytes, and countingAll you had to say was "try pasting or writing this and that" with a little bit of specificity. I don't get the approach that came through in this thread.Maybe next time it will be more fun and rewarding.

author: Ian.M
author_rank: Super Contributor
timestamp: November 14, 2015, 05:53:43 am
content: I was just pointing out that with the ready availability of SPI devices and the write block size limits of I2C EEPROMs, there is just no incentive for the development and test of I2C libraries optimised for large single message transfers.I'm glad you've figured out how to send sequential messages, but your way of doing it frankly sucks. As you know, the wire.write method truncates strings to its buffer size, so as long as you know that buffer size, all you have to do is to increment the pointer to the string by the buffer length then do another transfer:eg. something like this:Code:do {Wire.beginTransmission(5);Wire.write(TolstoyPtr+=BUFFER_LENGTH);Wire.endTransmission();} while(TolstoyPtr<TolstoyEndPtr);where TolstoyPtr and TolstoyEndPtr are both pointers to char, initialised to the beginning and end of the data array to be sent.However neither that nor your code can send a single message. It sends a start condition followed by the command byte (slave address), up to 32 bytes data followed by a stop condition, which means it sends a sequence of messages, one per Wire.endTransmission().If you want a continuous transfer you will need to write your own Wire.continueTransmission() method, based on the code from Wire.endTransmission() and Wire.beginTransmission(), that *DOESN'T* send a stop after the data block or the start followed by the slave address. You can then use the method you have written to tell the hardware to send the previous block and prepare the buffer for the next one.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 14, 2015, 06:42:29 am
content: Quote from: Ian.M on November 14, 2015, 05:53:43 amOK, I will study what you said in this post and try to figure it out.For the record, my code has hit a wall at 2012 Bytes - it doesn't transfer the full 63rd 32 Byte segment or the 64th - it just gets part way into the 63rd segment - as best I can tell it adds up to 2012 Bytes. Don't know if this is a code/Uno issue or some threshold with my scope or maybe just some of the scope settings.While it isn't 40k (haha, in a 32k Uno, I get it) the original sketch and the revised code has served some of the original purpose which was just to provide a test bed that would help me become more familiar with what the scope can do and how it operates - that's primarily what this project was about - just trying to get familiar with the digital channels, understand how the scope decodes I2C, segments memory at various acquisition rates, etc..... It was helpful/more interesting to get past 32 Bytes of a test bedThx again for your post above. I appreciate it.

author: Ian.M
author_rank: Super Contributor
timestamp: November 14, 2015, 07:16:52 am
content: The other problem that I have glossed over is how to get a contiguous string into memory that is longer than the compiler's string size limit. Some compilers support concatenation past the minimum ANSI C99 4096 character requirement, others don't.If yours does, probably your best bet is to write a PC program or script to take your chunk of text, break it up into convenient length lines (e.g. 64 characters), parse it to replace control codes and double quote (") characters with C escape sequences and spit it out into a file "tolstoy_c.h", with each line wrapped in double quotes.You would then add it to the code as:Code:const char Tolstoy={#include "tolstoy_c.h" // Inserts escaped Tolstoy data strings}const char* TolstoyPtr, TolstoyEndPtr;void InitTolstoyPtrs(void) { // *MUST* be in the same file as the array for sizeof() to work.TolstoyPtr=Tolstoy;TolstoyEndPtr=Tolstoy+sizeof(Tolstoy)/sizeof(Tolstoy);}Then you simply call InitTolstoyPtrs() before entering the loop to set up the pointers.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 14, 2015, 07:42:49 am
content: Quote from: Ian.M on November 14, 2015, 07:16:52 amRoger that. Thanks again!

author: Ian.M
author_rank: Super Contributor
timestamp: November 14, 2015, 08:13:20 am
content: Sorry about the b-----ed up formatting, I've fixed it now and also one small typo in the include file name.Here's what you'd have to convert the text to for "tolstoy_c.h"Code:"After Anna Mikhaylovna had driven off with her son to visit Coun""t Cyril Vladimirovich Bezukhov, Countess Rostova sat for a long ""time all alone applying her handkerchief to her eyes. At last sh""e rang.\n\n\"What is the matter with you, my dear?\" she said crossl""y to the maid who kept her waiting some minutes. \"Don't you wish ""to serve me? Then I'll find you another place.\"\n\nThe countess was"" upset by her friend's sorrow and humiliating poverty, and was th""erefore out of sorts, a state of mind which with her always found"" expression in calling her maid \"my dear\" and speaking to her wit""h exaggerated politeness.\n\n\"I am very sorry, ma'am,\" answered the"" maid.\n\n\"Ask the count to come to me.\"\n\nThe count came waddling in"" to see his wife with a rather guilty look as usual.\n\n\"Well, litt""le countess? What a saute of game au madere we are to have, my de""ar! I tasted it. The thousand rubles I paid for Taras were not il""l-spent. He is worth it!\"\n\nHe sat down by his wife, his elbows on"" his knees and his hands ruffling his gray hair.\n\n\"What are your"For that much, I did it in Word, tracking the line lengths manually to maintain (I hope) 64 C characters per individual string, which the compiler will concatenate into a single string in memory.Incidentally, the funny file name ending _c.h is because quite a few IDEs barf if you try to include anything other than a header (.h) file, but as a chunk of C source to insert in the main program, it isn't conceptually a header.

author: westfw
author_rank: Super Contributor
timestamp: November 14, 2015, 11:16:54 am
content: QuoteAre you doing the necessary things to put your text in flash (ie "PROGMEM":http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html)?limits at ~2000 bytes sounds suspiciously like you've used up all your RAM...I for one would be more willing to look at the code you have at this point, than I was to write code from scratch... Go ahead and post it (NOT 32k worth of tolstoy, though!)

author: Electro Fan
author_rank: Super Contributor
timestamp: November 14, 2015, 08:10:43 pm
content: Quote from: westfw on November 14, 2015, 11:16:54 amMight be a RAM limit, that would be good to determine. ThxIt's fundamentally the code that was posted in the sketch shown in the video earlier in this thread.There are no changes to the slave code.The changes to the master code are shown here://i2c Master Code(UNO)#include <Wire.h>void setup(){Serial.begin(9600); // gets to 62nd segment and some of 63rd for a total of 2012 BytesWire.begin();}void loop(){while(Serial.available()){char c = Serial.read();if(c == 'H'){Wire.beginTransmission(5);Wire.write("Help This Scope Operate 12345001");Wire.endTransmission();Wire.beginTransmission(5);Wire.write("ABCD EFG HIJK LMNOPQR STUVW002");Wire.endTransmission();Wire.beginTransmission(5);Wire.write("Help This Scope Operate 12345003");Wire.endTransmission();Wire.beginTransmission(5);Wire.write("ABCD EFG HIJK LMNOPQR STUVW004");Wire.endTransmission();continue patternWire.write("Help This Scope Operate 12345061");Wire.endTransmission();Wire.beginTransmission(5);Wire.write("ABCD EFG HIJK LMNOPQR STUVW062");Wire.endTransmission();Wire.beginTransmission(5);Wire.write("Help This Scope Operate 12345063");Wire.endTransmission();Wire.beginTransmission(5);Wire.write("ABCD EFG HIJK LMNOPQR STUVW064");Wire.endTransmission();}else if(c == 'L'){Wire.beginTransmission(5);Wire.write('L');Wire.endTransmission();}}}

author: Ian.M
author_rank: Super Contributor
timestamp: November 14, 2015, 08:29:15 pm
content: Does your slave Ack the last byte?

author: Electro Fan
author_rank: Super Contributor
timestamp: November 14, 2015, 11:04:24 pm
content: These are screen captures from the scope during decoder review.The scope is probing the communications between the Master and the Slave.Each of the full 62 Segments has 32 Bytes.Acks happen between characters.Attached are a few images - let me know if you have any questions.

author: Ian.M
author_rank: Super Contributor
timestamp: November 14, 2015, 11:26:13 pm
content: Not enough zoom on the last couple bytes transferred to see anything. You need to be able to see the individual bits with enough resolution to see their state at each clock edge, or if they transition between clock edges.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 02:06:43 am
content: Quote from: Ian.M on November 14, 2015, 11:26:13 pmHere you go - I started zoomed out with some Bytes to provide orientation at the end and then increasingly zoomed in to the last bit.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 02:18:38 am
content: Here is an ASCII M and a Binary M along with the clock - just making sure things line up as expected on the basics...?To be square (no pun intended) I am confident that the M is the character that was inputted by the code, and I believe the 1s and 0s pattern is the correct pattern for a Capital M, but I sometimes have a little trouble seeing where the 1s and 0s line up with the waveform - if you wanted to markup one of these and show were you think the corresponding 8 bits are in the M Byte that would be very interesting to see. (ie, show how and where 01001101 corresponds to the SDA line shown in D11) In previous work with decoders I could generally see where the 1s and 0s are represented by the Highs and Lows (and I get that the waveform can be Big Endian or Little Endian and Normal or Inverted polarity) but any which way I look at this M and the 1s and 0s I can't reason it out. I'm probably missing something but if not there might be some alignment issue with how it is rendering. Thx

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 02:58:22 am
content: Another example.Here is a Capital U (it looks a bit like a Capital V but it is a Capital U - you can see the U is in between the T to the left and the V to the right, as it was in the Uno code.)This is a very distinguishable character as it alternates 1s and 0s (10101010); this shows that the pattern should be read on the scope from right to left. Even so, its a little hard to see how the alternating 1s and 0s are aligned with the symbolism of the waveform??.I added the SCL and SDA labels - a nice feature but it's pretty clear which is the clock and which is the data.

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 03:06:06 am
content: Your scope's decoder display is FUGLY. It doesn't line up with the I2C SCL signal!To decode it by hand, I took the only screenshot that showed the end of the transfer and expanded the H axis then moved the SDA trace up to just above the clock for ease of decoding as I2C bit sampling occurs just after the +ve SCL edge.Result: The last byte (0x00) is Acked then the master sets a stop condition. Therefore it isn't a problem at the slave end.Do you have any other 0x00 (Null) bytes in the datastream? I'm suspicious because null is the C string terminator so maybe the half-borked wire library thinks there's no more to send!

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 03:10:11 am
content: Here is an ASCII A and a Binary A. The Binary pattern is correct but it's hard to see how it translates to the waveform.PS, this is of course not a code issue but a scope decoding issue... but it's all part of the integrated curriculum of trying to learn about scopes, decoding/digital, software, electronics, etc. Knowledge, skills, and tools in one area seem to help learn in the other areasIt's one of the great things about EEVblog

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 03:12:41 am
content: Quote from: Ian.M on November 15, 2015, 03:06:06 amI think our last couple posts crossed paths but I think they have both come to the same conclusion - there is an issue with getting the waveforms and the underlying bit patterns aligned. Said differently, the scope seems to decode logically, but not very well graphically.I need to figure this out. Not sure how long it will take but I'm on it. Hopefully it is operator error and not the scope.PS, nice work on your graphical alignment analysis. Thanks

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 03:53:30 am
content: It could well be the scope firmware. After over 17000 bits, it doesn't take much rounding error in the scope's measurement of the length of each SCL clock period to add up to a third of a byte shift. Does it align near the start of the message?

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 05:16:20 am
content: I went back to square one - just copied the sketch from the web that simply used one character but I changed H to U.This looks right unless you see something that looks amiss....In the off the shelf sketch it calls for the I2C address, then an acknowledgement, then a single character; let me know if you have a preferred character and I'll show you what that looks like in Binary and ASCII (and Hex if you want) so you can see if things line up properly. If that works, I can try upping the character count to see if/where things fall off the railroad tracks.

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 05:28:47 am
content: The first image looks wonky as well, but the rest look OK.Look at the two byte message in your second image. Everything lines up properly, and you can see that the Arduino I2C interface doesn't transmit bytes back to back, but has a delay after the ACK with the clock held low before the next byte (not unusual, to provide time to act on the ACK).The ACK bit SCL pulse in the first image is the one before the characteristic gap in the SCL clock. However its decoded value is shown approximately two scope divisions to the right of where it should be.How many bits from the start of the message was that?

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 05:35:45 am
content: This is the back to square one code for the images shown just above://i2c Master Code(UNO)#include <Wire.h>void setup(){Serial.begin(9600);Wire.begin();}void loop(){while(Serial.available()){char c = Serial.read();if(c == 'H'){Wire.beginTransmission(5);Wire.write('U');Wire.endTransmission();}else if(c == 'L'){Wire.beginTransmission(5);Wire.write('L');Wire.endTransmission();}}}

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 05:41:16 am
content: Ian, I was editing the last post and might have had a bad (old) image in the first image when you looked/commented; please take a look at the first image again and see if it still looks bad? Thx, EF

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 05:50:12 am
content: It looks like you took down the first image in post#73 after I commented on it. Did you post one of the old images by mistake? Try sending 0x5A ('Z'), because it has alterbating 1 and 0 apart from a doubled 1 in the middle so its much easier to count bytes.Unless your scope is reacting to fast glitches on SCL its serial data decoder display really shouldn't be skewed from the waveform like that. Try the longest possible repeated block of 'Z' filled strings that you can and look at the last few bytes of the message. If its skewed but is displaying 'Z' (or binary 01011010) the scope's protocol decoder dosplay is borked. If it shows anything else, the scope is responding to glitches on SCL which are causing it to mis-count the bits.

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 05:51:29 am
content: Yes. those are OK. It looks like the problem is only showing up after a *LOT* of data.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 05:53:31 am
content: Might have found the problem.Here is just a small progression in modifying the code.Previously, in the original off the shelf sketch from the video, the code sent one character as 'H'; when I modified to 'U' no problem. But when I change it to more than one character - which only seemed to work when I used "" instead of '' it falls off the railroad tracks. Look at 'U' vs. "UU" (both in the Binary form). I think my homemade code which changed 'H' to "H" and then started adding multiple characters was the beginning of the goof.

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 06:08:59 am
content: No that's clearly a scope problem. SDA goes low while SCL is high, clearly an I2C Start or Restart condition, but the scope's decoded data display is showing <Write 0x05> where that is happening. A start condition should be resynching the scope's decoder.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 06:15:05 am
content: Yep, I think you are right. I redid the original sketch with the 'H' and simply made it 'U' and the decode looks as shown below. I think I might beagainst a scope decode issue. I'm not 100% sure yet, but it is looking like something is goofy with the scope decoding process. It gets the ASCII and Binary right but it isn't lining up graphically.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 06:18:04 am
content: I have a few things to try. I'm going to see if it behaves the same way with I2C on the analog channels. I'm also going to see how it performs on the analog channels and the digital channels with RS232. I'll keep you posted here as I learn more. Thanks very much for hanging in there with me on this - your experience not only on the coding but with I2C has been very helpful.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 06:35:03 am
content: Ian, here is analog I2C. Waveforms definitely not as clean but the alignment makes more sense?

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 06:43:07 am
content: That's much happier. Now try it on a *Looooooooong* message, and make sure you have the stop condition in view so you can be certain of the actual alignment

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 06:57:44 am
content: A step at a time, here are 32 Bytes with the sequence"UUUABCDEFGHIJKLMNOPQRSTUVWXYZUUU"

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 07:10:48 am
content: That does look OK, but for ease of reading it manually, set the gain to get 1 div high waveforms, and put the the SCL signal immediately below and very close to SDA. The decoded data should be below SCL (as it is), but if possible closer, so any alignment skew is more obvious

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 07:11:13 am
content: Here are two 32 Byte segments (analog again).38 are the two segments39 shows near the end of segment 001 the U looks lined up40 is the transition between segment 001 and 00241 shows near the end of segment 002 the U looks lined up42 shows the very end of segment 002

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 07:11:55 am
content: Quote from: Ian.M on November 15, 2015, 07:10:48 amWill do on next batch - but that will require overlaying SCL and SDA, is that what you prefer?

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 07:27:58 am
content: Quote from: Ian.M on November 15, 2015, 07:10:48 amI think 44 is what you are looking for - it shows how the decodes line up on the clk; 43 shows how it the decodes line up on the data; I kind of like 43 but if you want to standardize on 44 that's A-Ok. (Or I can squeeze them tighter with the decodes in the middle so we can see how they line up against both the clk and the data.) Here's 45 as an example.

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 07:35:40 am
content: I can live with them overlaid with at least 1/2 division offset, but its better to have the top of SCL fractionally below the bottom of SDA. That way all you have to do is look at the middle of the two waveforms to read them manually. See the image I posted that I had tweaked to decode it in post #69. Obviously if you were looking for waveform distortions, you'd separate them enough to see any ringing etc. but for checking the data content, the less vertical distance (within reason) you have to move your point of focus, the better.If you can bring SCL right up to the decode trace, you can easily check for skew by seeing if the ACK bit display is centered on the last SCL pulse in each group of nine.image 44 is OK, but would benefit by reducing the amplitude of both SDA and SCL by a factor of about 2 using the input attenuators.Decode trace in the middle is a royal PITA as it makes it much harder to check by manual decoding.Waveforms that show the scope and signal source working as expected aren't very interesting. Concentrate on the ones you believe to show problems!Be glad you aren't trying to resolve long I2C messages on an old delay timebase analog boatanchor!(Not my photo - I'd never have the trace blooming like that)

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 07:42:27 am
content: Assuming you prefer the 44 layout, here is the end of the second segment

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 07:48:47 am
content: And here is the U from the second segment (002); I like it because it's recognizable and it helps show alignment; what do you think? Does it grade out ok or is it out of alignment? Maybe the data is shifted a tad right? Or maybe that's just the data trying to catch-up with the clock?

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 07:56:24 am
content: 46 Looks fine. See how easy to read manually it is? Just let your eye follow along the midpoint horizontally and if the top of the blue SCL has the yellow SDA next to it, its a zero bit, otherwise its a one bit. Within a message (apart from restart bits in a compound message) SDA is only permitted to change when SCL is low, so a small lag from SCL trailing edge to SDA changing is expected.47 is showing very slight skew on the decoder trace, its no more than 1/5 of a bit and may even just be an artefact of the zoom setting. Zoom in the X axis by 50% and see if it lines up better.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 07:58:43 am
content: Looks like about 420 ns offset - don't know if that's normal or a problem; probably not good enough to find particles in the Hadron Collider but maybe good enough for decoding I2C? When I get back to the 62-64 segment test we can see if it's holding at 420 ns which could just be the response time between the data and the clock, or if it's something longer which would likely be some kind of drift.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 08:03:49 am
content: Quote from: Ian.M on November 15, 2015, 07:56:24 amVery good advice and info!! Thx

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 08:08:10 am
content: Looks like the signals are 5V; I noticed I had both SCL and SDA set to trigger at 1.34V. The fall time on SCL looks a little steeper than the rise time on SDA. Maybe if I change the trigger we could pull them into alignment a little better - but I presume the trigger level should be set the same on both, or not so? What do you recommend for the two trigger levels?

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 08:14:35 am
content: Actually, the more we get into this, it looks like the delta between SCL and SDA is less than 420 ns. I measured in the middle (about 50%) on both SCL and SDA. Generally, rise time and fall time measurements are at 10% and 90% (or maybe 20 and 80). Setting that aside, I think we can see that SDA starts to rise probably closer to within 300 ns of SCL going low,so what we might be seeing is the limitation of my 70 MHz scope.- I just corrected a couple things in the posts; at first I thought the delta was 4 ns and that seemed mighty fine, but it's actually 300 ns so I doubt that is a limitation of the scope's rise time.

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 08:20:33 am
content: See that glitch (hump) on the high part of SDA in the fourth division to the right of the center. That looks like capacitive cross-coupling between SDA and SCL. Its not a problem at the moment, but if you push the speed up to 400KHz and have a longer bus, it could become an issue. What pullup resistors are you using?If you are talking about the trigger levels for the protocol decoder, check the I2C standard. Modern devices use 30% and 70% (of VDD) logic threshholds, so the data should decode the same anywhere within that range. If it doesn't, you've got signal integrity problems.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 08:31:19 am
content: Quote from: Ian.M on November 15, 2015, 08:20:33 amWow, the plot thickens. You know, I thought I had 200 ohm resistors but my eyes failed me; I missed a yellow band so I think I have 4k resistors - might be less than optimum? I think they are just quarter Watt so they are sort of small and the yellow was right on the hump and kind of blended in. Let me know if you recommend different value and I'll change them.Scratch all that - turns out my eyes must have been ok but my memory was off, duh. I just looked at the original design and it called for 4.7k Ohm resistors - so I think I'm ok on the resistors unless you think otherwise.What else could be causing the hump on all the highs for SDA? I've never seen that type of hump before. I've played with the probe ground but that didn't seem to matter. Also tried two different probes (Rigol and Tektronix), no diff. I also see some runts (I think that's what they are). Overall, the signals don't look very pretty - but it's funny how these crummy analog signals are making the decoder happier than the beautiful digital signals. I'm digital signal decoding issue had to do with software/firmware instead of signal integrity. But if I can clean up the analog signals that would be good.Also, at 1.34V I'm under the 30% guideline on trigger. So, I'll bump it up to 50% on the assumption that if anywhere between 30 and 70 should be the same 50 should be a good level.This is a great learning experience - Thank You! EF

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 08:39:14 am
content: 200R is rather low. Many I2C devices wont like that. Try 2K2.50% is a good compromise if you just want to see whats on the bus or if you already know the levelos are always valid, but if you are checking for signal problems, you need to check it at both 30% and 70%, and look for any decoded data changes between them.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 08:45:15 am
content: Quote from: Ian.M on November 15, 2015, 08:39:14 amJust fixed the post above regarding resistors - they are ~4.57k

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 08:54:38 am
content: Fair enough. Don't go below 2K2 without studying the datasheets of ALL the devices on the bus CAREFULLY. If you go too low, at best you get signal integrity issues because one or more devices are having difficulty sinking enough current to get a valid logic '0', at worst, you damage something. If you need to speed up the rise times even more, the best choice is active pullups (e.g.LTC4311), not lower value resistors.However your waveforms look fine as-is. Anything that reaches 90% of Vdd before the next clock edge is generally fine.

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 09:12:28 am
content: Quote from: Ian.M on November 15, 2015, 08:20:33 amAny chance capacitive cross-coupling could come from having SDA and SCL just a few holes apart on a bread-board? Or is more likely to be some other (wires, connections) issue?

author: Electro Fan
author_rank: Super Contributor
timestamp: November 15, 2015, 09:14:47 am
content: I'm going to sign off for the day but I'll test longer segments and post how well time aligned things are on the last segment. I'll also try RS232 with analog and digital, and then revisit I2C with digital. Thanks again!

author: Ian.M
author_rank: Super Contributor
timestamp: November 15, 2015, 09:26:17 am
content: Quote from: Electro Fan on November 15, 2015, 09:12:28 amStrip to strip capacitance isn't that high in a good quality breadboard. Boss used to quote 0.5pF for their Bimboard range, and I've checked with a capmeter that its not more than a pF or so. Wiring capacitance or inductive coupling is probably responsible.Quote from: Electro Fan on November 15, 2015, 09:14:47 am+1