Problems with ATTiny and Wire

I have several questions about the Wire library.

  1. I read this line in many sketches using I2C:
#include <Wire.h>

How can I be sure it's the buit-in Arduino library? I'm uncertain because if I google 'wire.h github'
the many results include several apparently different libraries with that exact name.

  1. Why is Wire not in the Arduino section here?

  1. During research I saw that "The Wire library ... is included in all board packages, so you don't need to install it manually in order to use it." Doesn't this imply that
#include <Wire.h>

never needs adding in any sketch? Like Arduino.h, SoftwareSerial.h, and other built in Arduino libraries'.

  1. How do I interpret the following two different results using the same include line?
// I entered the following manually
#include <Wire.h>
void setup()
{
 }
void loop()
{
}

That gave compile errors with these lines near the end:

Multiple libraries were found for "Wire.h"
 Used: C:\Users\terry\Dropbox\Electronics\Arduino\SKETCHES\libraries\Wire
 Not used: C:\Users\terry\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\libraries\Wire
Using library Wire at version 2.0.0 in folder: C:\Users\terry\Dropbox\Electronics\Arduino\SKETCHES\libraries\Wire 
"C:\\Users\\terry\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-size" -A "C:\\Users\\terry\\AppData\\Local\\Temp\\arduino_build_417919/WirePuzzle-1.ino.elf"

If instead I used Sketch > Include Library, and selected Wire in the 'Contributed' section, that gave this very different result:

// I used 'Include Library' here
#include <SoftI2CMaster.h>
#include <SoftWire.h>
#include <twi.h>
#include <Wire.h>
#include <WireS.h>

void setup()
{
 }

void loop()
{
}

That gave an 800 line error report, mostly incomprehensible to me, ending with:

Using library Wire at version 2.0.0 in folder: C:\Users\terry\Dropbox\Electronics\Arduino\SKETCHES\libraries\Wire 
exit status 1
Error compiling for board Arduino Uno.

The full error report is here:

Full error report

It depends on how the Arduino board support package is written. More than half of the packages were written not by Arduino, but by third-party groups of programmers. And not all packages automatically include the Wire library in the code. In some you have to enable it yourself.

By the way, the SoftwareSerial.h library is not included by default, you have to include it explicitly.

Is part of the confusion the difference between 'installed with the IDE'(SofwareSerial.h, Wire.h), and automatically included 'behind the curtain'(Arduino.h)? Your wording seems to blur the difference, but there is one.

I think the answer to both is that you somehow managed to put a copy of SOME version of Wire.h meant for SOME unknown flavor of Arduino board in the libraries folder under your SKETCHES folder. I'm pretty sure it doesn't belong there. As you noted the the proper version for every board is part of the core package for that board and is stored somewhere in the installation where you hopefully won't mess with it.

4 Likes

If you are not an Arduino Core developer, you should never need to install third-party Wire libraries via the Library manager.

Thanks, that sounds right. I’ll get back onto the case in the morning. Probably start by deleting the Wire entry from my \libraries folder.

All replies so far appreciated thanks.

As a hobbyist I’m definitely not a developer of any flavour! But your point is very relevant. My four questions arose because I’ve been working on programming the several Tiny boards I bought cheaply a year or two ago. With varying degeees of success and failure. It seems this has resulted in a ‘special’ version of Wire.h being installed.

As Tiny cannot access the serial monitor I need to use my LCD 1602 for debugging. And for the particular projects I’m working on I need a DS3231. So that’s two I2C devices. A challenge for the ATTiiny 88 board.

I’ll report back here as I learn more about what’s going on. But one thing is already painfully clear: giving different libraries exactly the same name guarantees trouble!

Not strictly correct.............. https://www.youtube.com/watch?v=HJ4mhXv-MXo

I've moved two conflicting 'Wire' libraries' from \libraries to a temporary holding folder.

WireConflictingLibraries

(The \libraries folder currently therefore now has no such entry.)

Examining the properties, I was able to rename them. So the one that generated those five libraries yesterday when using 'Include Library' arose from my Tiny programming attempts, using the third of these:
https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json
http://digistump.com/package_digistump_index.json
http://drazzy.com/package_drazzy.com_index.json
https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json
https://raw.githubusercontent.com/MHEtLive/arduino-boards-index/master/package_mhetlive_index.json

In case it proves relevant, its properties are:

name=Wire
version=2.0.0
author=Spence Konde and others
maintainer=Spence Konde <spencekonde@gmail.com>
sentence=Supports I2C master or slave operation on all ATTinyCore-supported parts
paragraph=YOU MUST ALWAYS USE HARDWARE PULLUP RESISTORS! Otherwise, this is intended as a "drop-in" replacement for the normal Wire library. Unlike ATmega parts, most classic ATtiny devices do not have a proper hardware TWI interface - they have a USI, or slave only interface. This library picks the appropriate hardware and presents a compatible API. Changing clock speed doesn't work. ATtiny841, 1634, 828, and 441 as master provide no way to determine if a timeout occurred.
category=Communication
url=http://www.arduino.cc/en/Reference/Wire
architectures=avr

I'm technically out of my depth here. How do others interpret "...this is intended as a "drop-in" replacement for the normal Wire library"?
When using it instead of the built-in library for the sketch below, on a UNO, it would not compile. Is that to be expected? This question only arises because at present I am repeatedly switching between developing sketches for UNO and Tiny.

(Probably a lost cause - too much like hard work!).

Rephrasing an earlier gripe as a question: why does the Arduino team not insist that developers give libraries UNIQUE names before they get space on the Arduino IDE? For example 'Wire_DrAzzy', etc.

EDIT: Forgot the sketch:

/*  Thu 25 Apr 2024; working OK on UNO, initially with default
 *  date/time. Entering 'u' in the Serial Monitor switches to
 *  Edit Mode. Then enter the 6 elements for current date & time,
 *  pressing Enter after each.
 *  
 *  To have any chance of working on my Tiny board this will at
 *  least need removal of all Serial code. I will no  doubt hit
 *  problems again with the Wire library. From previous experience
 *  they could remain afterwards, when running on UNO etc.
*/

#include <Wire.h> // for I2C communication, 2 devices in this case
#include <LiquidCrystal_I2C.h> // for LCD
#include <RTClib.h> // for RTC

LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD with I2C address 0x27, 16 characters per line, 2 lines
RTC_DS3231 rtc; // RTC for DS3231 module, address fixed at 0x68
/************************************************************/
void setup()
{
  Serial.begin(115200);
  delay(200);
  Serial.print(F( "\n" __FILE__ "\n" __DATE__ " " __TIME__ "\n" ));

  lcd.init(); // initialize the lcd
  lcd.backlight();

  // Show LCD is working & identify sketch name
  lcd.setCursor(0, 0);
  lcd.print("Sketch name:");
  lcd.setCursor(0, 1);
  lcd.print("LCD-RTClib-3");
  delay(3000);
  lcd.clear();

  rtc.begin(); // initialize rtc
}
/************************************************************/
void loop()
{
  updateLCD(); // Update LCD text

  if (Serial.available())
  {
    char input = Serial.read();
    if (input == 'u') updateRTC();  // update RTC time
  }
}
/************************************************************/
// Update RTC time with user input
void updateRTC()
{
  lcd.clear();  // clear LCD display
  lcd.setCursor(0, 0);
  lcd.print("Edit Mode...");

  // Ask for new date and time
  const char txt[6][15] = { "year [4-digit]", "month [1~12]", "day [1~31]",
                            "hours [0~23]", "minutes [0~59]", "seconds [0~59]"
                          };
  String str = "";
  long newDate[6];

  while (Serial.available())
  {
    Serial.read();  // clear serial buffer
  }

  for (int i = 0; i < 6; i++)
  {

    Serial.print("Enter ");
    Serial.print(txt[i]);
    Serial.print(": ");

    while (!Serial.available())
    {
      ; // wait for user input
    }

    str = Serial.readString();  // read user input
    newDate[i] = str.toInt();   // convert user input to number and save to array

    Serial.println(newDate[i]); // show user input
  }

  // update RTC
  rtc.adjust(DateTime(newDate[0], newDate[1], newDate[2], newDate[3], newDate[4], newDate[5]));
  Serial.println("RTC Updated!");
}
/************************************************************/
void updateLCD()
{
  /*
     create array to convert digit days to words:

     0 = Sunday    |   4 = Thursday
     1 = Monday    |   5 = Friday
     2 = Tuesday   |   6 = Saturday
     3 = Wednesday |
  */
  const char dayInWords[7][4] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};

  /*
     create array to convert digit months to words:

     0 = [unused]  |
     1 = January   |   6 = June
     2 = February  |   7 = July
     3 = March     |   8 = August
     4 = April     |   9 = September
     5 = May       |   10 = October
     6 = June      |   11 = November
     7 = July      |   12 = December
  */
  const char monthInWords[13][4] = {" ", "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
                                    "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
                                   };

  // get time and date from RTC and save in variables
  DateTime rtcTime = rtc.now();

  int ss = rtcTime.second();
  int mm = rtcTime.minute();
  int hh = rtcTime.twelveHour();
  int DD = rtcTime.dayOfTheWeek();
  int dd = rtcTime.day();
  int MM = rtcTime.month();
  int yyyy = rtcTime.year();

  // move LCD cursor to upper-left position
  lcd.setCursor(0, 0);

  // print date in dd-MMM-yyyy format and day of week
  if (dd < 10) lcd.print("0");  // add preceeding '0' if number is less than 10
  lcd.print(dd);
  lcd.print("-");
  lcd.print(monthInWords[MM]);
  lcd.print("-");
  lcd.print(yyyy);

  lcd.print("  ");
  lcd.print(dayInWords[DD]);

  // move LCD cursor to lower-left position
  lcd.setCursor(0, 1);

  // print time in 12H format
  if (hh < 10) lcd.print("0");
  lcd.print(hh);
  lcd.print(':');

  if (mm < 10) lcd.print("0");
  lcd.print(mm);
  lcd.print(':');

  if (ss < 10) lcd.print("0");
  lcd.print(ss);

  if (rtcTime.isPM()) lcd.print(" PM"); // print AM/PM indication
  else lcd.print(" AM");
}

Thanks, I'll watch that soon. Presumably OK for my 88 as well as that 85. But I did spend a day or two a while ago trying what I assume might be a similar approach to getting Serial working, but no joy.

In what sense?

  1. Low memory capacity
  2. I've not yet managed to successfully program my ATTiny88 board with any sketch using both devices.

I interpret it as it provides the same API calls as the "normal" Wire library when used on the intended platform.

So, in terms I can understand, what changes should I make to the sketch before using the UNO to program the Tiny? Should I at least delete

#include <Wire.h> // for I2C communication, 2 devices in this case

and then use Sketch > Include Library?

I've never used a Tiny core. So, my answer is based on the assumption that it works like every other Arduino Core. If that's the case, then you have to change ....... NOTHING. The Arduino IDE should pull the proper version of the library from the core's install directory (based on the IDE's "Board:" setting). That's why none of those files belong in the ..\sketchbook\libraries folder.

Thanks, understood.

That assumption doesn't seem borne out by the tests I've been doing with sketches like that I presented in post #9 with this line:

#include <Wire.h>

With the board set to ATTiny 88/48 (No Bootloader), such sketches fail, yet they run OK on UNO.

But perhaps I've misunderstood. Are you really assuming that the #include automatically calls in different code when the Tiny board has been chosen?

BTW, sketches which don't use the DS3231 work without the Wire library, on both UNO and Tiny. Perhaps the LCD library handles the I2C stuff and/or calls Wire itself?

Fails to compile or fails to run?

I'm not assuming anything. I know that the IDE #include(s) different source code for compilation of platform-dependent functions depending on it's Board type setting.

If compilation with the ATTiny core doesn't behave that way, then it's an odd ball among all other boards in the Arduino ecosystem.

They do. In order for it to go in the library manager it must have a unique library name. It's one of the checks that happens when you push to the library registry.

That doesn't mean the include file has to have a unique name. That would be impossible.