Wrote a library to simplify sketch. All compiles in IDE, but setup won't run.

Hello,

So here is what I’m doing. I have six printer carriages that each have an encoder strip, quadrature encoder and DC motor. For each of these, I have an arduino uno serving as a position decoder and motor controller. The arduinos are I2C slaves to a Teensy 3.5 board which requests the position from the Unos, receives midi notes which dictate the next position to set the carriages at, and sends commands to the uno to tell it what to set the PWM to and what DOs to toggle. I am able to read the encoders via I2C in an earlier version of my code.

Now since each printer carriage can have a different travel length, lines per inch of the code strip, and MIDI note offset, I thought it would greatly organize my sketch create a class to handle those properties and also the methods for sending that information via I2C. I then followed the arduino site’s tutorial for creating a library. After getting it how I wanted it, I put the header and cpp files in an appropriately named folder in the arduino libraries directory, revised my Teensy 3.5 sketch to use the library, Verified, addressed all the errors in the sketch and library files, and now it can be verified without any errors showing. I uploaded my code to the teensy while it was connected to the Unos via I2C to read the encoders, but I was not getting the encoder positions to print in the Serial window like I was expecting. In fact, after unplugging the Teensy entirely from the circuits, adding Serial.println(“SETUP”); to the beginning of setup(), and reuploading, it appears that my setup function isn’t being executed at all.

I’m certain I’ve made a mistake in my library, but without anymore compiler warnings to work from, I’m not sure how to troubleshoot this issue. Can you help me figure out what’s wrong in my code?

Teensy 3.5 configured as a USB Type: MIDI - Maestro.ino and Maersto_old
Library: DiddleyBow.h and .cpp
Arduino Uno: Decotor.ino

Maestro_old.ino (2.38 KB)

Maestro.ino (4.29 KB)

DiddleyBow.h (1.53 KB)

DiddleyBow.cpp (2.43 KB)

Decotor.ino (2.52 KB)

I'm pretty sure that sketch doesn't compile as usbMIDI is not defined anywhere.

But the problem with your library is somewhere else. Remove the findFrets() call from the classes constructor. Put it into a begin() (you may find a better name for it) method which you later call in the setup().

The reason is easy: the constructor is called very early in the sketch when the Arduino environment isn't initialized yet. For example, you use the Wire I2C interface but you initialize that hardware not before the setup() was called (Wire.begin()), so any call there will fail. So be sure that you call the begin() method of your own class after you called Wire.begin() (in setup()).

Ahhh, okay. I will try this later. Thank you for the advice.

In Teensyduino, rather than including a usbMIDI library, you select it as a "USB Type" from the modified Arduino IDE menu (see attachment).

It is described here if you are interested: Teensyduino: Using USB MIDI with Teensy on the Arduino IDE

So the problem was actually that I did not put Wire.begin() before calling the findFrets() function in the constructor. findFrets() makes a call to home() which tries to send data over I2C. The example that you gave of needing to begin I2C before using it was actually more relevant than you might have thought! I must give credit to user Rajat_Bandejiya who apparently created an account on the forum just to point this out amidst some other ramblings about why programs hang at line Wire.endTransmission() (his only post).

Another piece of the puzzle was perhaps giving setup enough time to connect to the computer after uploading(?) This code seemed to help:

void setup() {
... // setup code not needing to print
	Serial.begin(115200);
	while (!Serial && millis() < 4000 );
	Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
	Serial.println("SETUP");
... // rest of setup where printing will work if connected when above times out ...

Evidently (on my computer at least), you can use functions in a constructor for a class, and evidently you can use functions outside of setup() or loop() (i.e. the constructor function to set variable bow). There is definitely a grain of truth to what you said, though. You can’t execute a Serial.begin() or Wire.begin() outside of setup or loop, as this gives error:

error: 'Serial' does not name a type
 Serial.begin();
 ^

error: 'Wire' does not name a type
 Wire.begin();
 ^

For some reason, it works fine within the constructor of the defined in a library. I can now read things printed in setup(), and I can read and write via I2C. In any case thanks for your input, it definitely helped me get to where I am now.

Just make sure that the libraries you initialize before setup() are not trying to use millis(), micros(), delay(), or analogWrite() since those aren't initialized until just before setup() is called.