Не компилится скетч на Digispark Attiny85

Пытаюсь скомпилить скетч для Attiny85 на Digispark Attiny85.
Получаю ошибку

....\ina226_driver.cpp: In member function 'void Ina226Driver::calibrate(float, float)':
...\ina226_driver.cpp:31:19: error: 'InaReg' is not a class or namespace
   writeRegister16(InaReg::Calibration, calibration_value);

И тоже самое для всех функций…
Компилю на arduino IDE 2.2, для платы Digispark (Default - 16.5 mhz).
Если попытаться этот же скетч скомпилить для платы ATtiny25/45/85, всё прокатывает.
Но залить скомпиленный скетч не могу, т.к. он требует программатор…
Вот скетч (т.к. дисплея и Serial нет, закомментировал относящиеся к ним блоки)

/*

  PowerMeter
  A voltage, current and power meter using the INA226, with an ATtiny85 driving the process and displaying measurements to a 128X32 OLED display.

  For info and circuit diagrams see https://github.com/tardate/LittleArduinoProjects/tree/master/Equipment/PowerMeter

 */

#include "ina226_driver.h"
//
#if defined(__AVR_ATtiny85__)
  #include <TinyWireM.h>
//  #include <Tiny4kOLED.h>
//  #define LARGE_FONT FONT8X16
//  #define SMALL_FONT FONT6X8
#else
  #include <U8x8lib.h>
  U8X8_SSD1306_128X32_UNIVISION_HW_I2C oled(U8X8_PIN_NONE);
  const uint8_t * LARGE_FONT = u8x8_font_px437wyse700a_2x2_r;
  const uint8_t * SMALL_FONT = u8x8_font_amstrad_cpc_extended_r;
  const uint32_t SERIAL_SPEED = 115200;
#endif
//
const float   R_SHUNT      = 0.046758; // needs to be replaced with the actual shunt resistance (in ohms)
const float   MAX_BUS_AMPS = 0.500; // set desired full-range current (used to scale the calibration factor)
const uint8_t INA_ADDR     = 0x40; // I²C address of the INA226

const uint16_t DELAY_SPLASH = 2000; // ms delay on the initial splash screen
const uint16_t DELAY_BETWEEN_SAMPLES = 1000; // ms delay between updating the display with a new value

Ina226Driver ina = Ina226Driver();


void setup() {
/*  
  #ifdef HAVE_HWSERIAL0
    Serial.begin(SERIAL_SPEED);
    while (!Serial) {}
    Serial.print("\n\nINA226 Power Meter\n");
  #endif
*/
  ina.begin(INA_ADDR);
  ina.calibrate(R_SHUNT, MAX_BUS_AMPS);
/*
  #if defined(__AVR_ATtiny85__)
    oled.begin();
    oled.clear();
    oled.switchRenderFrame();
    oled.clear();
    oled.switchRenderFrame();
    oled.on();
    oled.setFont(LARGE_FONT);
    oled.setCursor(40, 0); oled.print(F("INA226"));
    oled.setFont(SMALL_FONT);
    oled.setCursor(26, 2); oled.print(F("Power  Meter"));
    oled.setCursor(16, 3); oled.print(F("leap.tardate.com"));
  #else
    oled.begin();
    oled.setFont(LARGE_FONT);
    oled.drawString(2, 0, "INA226");
    oled.setFont(SMALL_FONT);
    oled.drawString(2, 2, "Power  Meter");
    oled.drawString(0, 3, "leap.tardate.com");
  #endif
*/
  delay(DELAY_SPLASH);
/*
  #if defined(__AVR_ATtiny85__)
    oled.clear();
    oled.setFont(LARGE_FONT);
    oled.setCursor(94, 0); oled.print(F("V"));
    oled.setFont(SMALL_FONT);
    oled.setCursor(94, 2); oled.print(F("mA"));
    oled.setCursor(94, 3); oled.print(F("mW"));
  #else
    oled.clearDisplay();
    oled.setFont(LARGE_FONT);
    oled.drawString(14, 0, "V");
    oled.setFont(SMALL_FONT);
    oled.drawString(14, 2, "mA");
    oled.drawString(14, 3, "mW");
  #endif
*/  
}


void loop() {
  static char bus_V[15], shunt_mV[15], current_mA[15], bus_mW[15];

  dtostrf(ina.readBusVoltage()      , 7, 3, bus_V);
  dtostrf(ina.readShuntVoltage()    , 9, 3, shunt_mV);
  dtostrf(ina.readCurrent() * 1000.0, 9, 3, current_mA);
  dtostrf(ina.readPower() * 1000.0  , 9, 3, bus_mW);
/*
  #if defined(__AVR_ATtiny85__)
    oled.setFont(LARGE_FONT);
    oled.setCursor(35, 0); oled.print(bus_V);
    oled.setFont(SMALL_FONT);
    oled.setCursor(36, 2); oled.print(current_mA);
    oled.setCursor(36, 3); oled.print(bus_mW);
  #else
    oled.setFont(LARGE_FONT);
    oled.drawString(0, 0, bus_V);
    oled.setFont(SMALL_FONT);
    oled.drawString(4, 2, current_mA);
    oled.drawString(4, 3, bus_mW);
  #endif
*/
  delay(DELAY_BETWEEN_SAMPLES);
}

ina226_driver.h

#pragma once

#include <Arduino.h>

#if defined(__AVR_ATtiny85__)
  #include <TinyWireM.h>
  #define Wire TinyWireM
#else
  #include <Wire.h>
#endif


enum InaReg : uint8_t {
  Configuration    = 0x00,
  ShuntVoltage     = 0x01,
  BusVoltage       = 0x02,
  Power            = 0x03,
  Current          = 0x04,
  Calibration      = 0x05,
  MaskEnable       = 0x06,
  AlertLimit       = 0x07,
  ManID            = 0xFE,
  DieID            = 0xFF,
};
//
/**
 * A simplified INA226 interface using the Wire library
 */
class Ina226Driver {
  public:

    /**
     * Command: init for specified I²C address
     */
    void begin(uint8_t address);

    /**
     * Command: set calibration for particular shunt and current combination
     */
    void calibrate(float shunt_resistance, float max_current);

    /**
     * Returns: the latest bus voltage (in volts)
     */
    float readBusVoltage(void);
    /**
     * Returns: the latest shunt voltage (in millivolts)
     */
    float readShuntVoltage(void);

    /**
     * Returns: the latest bus/shunt current (in amps)
     */
    float readCurrent(void);

    /**
     * Returns: the latest bus power (in watts)
     */
    float readPower(void);

  private:

    uint8_t address;

    float shunt_resistance;
    uint16_t calibration_value;

    float current_LSB;
    float power_LSB;

    int16_t readRegister16(InaReg reg);
    void writeRegister16(InaReg reg, uint16_t value);
};

ina226_driver.cpp

#include "ina226_driver.h"


void Ina226Driver::begin(uint8_t address) {
  Wire.begin();
  this->address = address;
}


void Ina226Driver::calibrate(float shunt_resistance, float max_current) {
  this->shunt_resistance = shunt_resistance;

  float minimum_lsb = max_current / 32768;
  current_LSB = ceil(minimum_lsb * 10000000000) / 10000000000;
  power_LSB = current_LSB * 25;
  calibration_value = (uint16_t)((512) / (current_LSB * 100000 * shunt_resistance));
/*
  #ifdef HAVE_HWSERIAL0
    Serial.print("Manufacturer ID : "); Serial.println(readRegister16(InaReg::ManID), HEX);
    Serial.print("Die ID          : "); Serial.println(readRegister16(InaReg::DieID), HEX);
    Serial.print("Calibrating for shunt resistance of ");
      Serial.print(shunt_resistance, 3);
      Serial.print("Ω and maximum current of ");
      Serial.print(max_current, 3);
      Serial.println("A");
    Serial.print("  * current_LSB : "); Serial.print(current_LSB * 1000.0, 6); Serial.println("mA");
    Serial.print("  * power_LSB   : "); Serial.print(power_LSB * 1000.0, 6); Serial.println("mW");
    Serial.print("  * CAL         : "); Serial.println(calibration_value);
  #endif
*/
  writeRegister16(InaReg::Calibration, calibration_value);
}


float Ina226Driver::readBusVoltage(void) {
  int16_t voltage = readRegister16(InaReg::BusVoltage);
  return (voltage * 0.00125);
}


float Ina226Driver::readShuntVoltage(void) {
  float voltage = readRegister16(InaReg::ShuntVoltage);
  return (voltage * 0.0025);
}


float Ina226Driver::readCurrent(void) {
  return (readRegister16(InaReg::Current) * current_LSB);

}


float Ina226Driver::readPower(void) {
  return (readRegister16(InaReg::Power) * power_LSB);
}


int16_t Ina226Driver::readRegister16(InaReg reg) {
  Wire.beginTransmission(address);
  Wire.write(reg);
  Wire.endTransmission();

  Wire.requestFrom(address, (uint8_t)2);
  uint8_t hi = Wire.read();
  uint8_t lo = Wire.read();

  return hi << 8 | lo;
}


void Ina226Driver::writeRegister16(InaReg reg, uint16_t value) {
  uint8_t lo = (uint8_t)value;
  uint8_t hi = value >>= 8;

  Wire.beginTransmission(address);
  Wire.write(reg);
  Wire.write(hi);
  Wire.write(lo);
  Wire.endTransmission();
}

Пытался погуглить по тексту ошибки - ничего кроме проблемы с многократным включением #include не нашёл…
Да и с другой платой скетч компилится!

Либо уберите везде, где используются константы перечисления, указание класса ( InaReg:: ), либо при описании перечисления добавьте слово class сразу после слова enum. Но во втором случае оно потребует от Вас определённой дисциплины, например, константы нельзя будет использовать в качестве int.

А typedef перед enum не поможет?

Попробуйте так, и нажмите записать загрузчик

Благодарю! Помогло.

Не помогло.

Не стал пробовать, т.к. прокатила первая рекомендация.

P.S. Спрошу заодно - подскажите, пожалуйста, лёгкую библиотеку Software Serial для Digispark.
Опасаюсь, что не хватит места в прогмем. Только то, что выложил выше, уже занимает 68%.

Attiny45/85 (Optiboot) - отсюда http://drazzy.com/package_drazzy.com_index.json ?

1 лайк

Feofan, не понял… Это вы о чём?

Спойлер

Ядро откуда?

Да, ATtinyCore

Ок. Спасибо.

А у меня почему-то в ATtinyCore нет ATtiny85 (Micronucleus/DigiSpark).
И само ядро выше версии 1.3.3 не ставится, матюгает Failed to install platform:…

P.S. А насчёт Software Serial для DigiSpark что-нибудь подскажете?
Подключил DigisparkSoftSerial и всё - 96% флеши… :frowning:

Дигиспарк имеет на борту половину обычного Seriala. Сейчас не вспомню на какой ноге, но на передачу данных он точно работает (частоту чипа надо выбрать 16 MHz).

А как нагуглить эту ногу?

Так - Digispark (16mhz No USB)?

P.S. Serial.begin(9600), Serial.print(“xxxx”) компилится без SoftSerial.

а у тебя что, нано или уно нету?

Есть. Даже USBASP нашёл. Не уверен, правда, что он живой, но винда его видит.
Только это уже не актуально (см. выше).

да я увидел, только с оптибутом как-то не попробовал даже, лень переходник подключать, сделал программатор из двух маленьких колодок под дюпоны, в одной нано посажена, в другую вставляю голый чип, лью, а дальше в плату дигиспарка пересаживаю

Офигеть! И где ж найти эту волшебную ногу!)
Нет Сериала в Дигиспарке! И никогда не было.
Если нужна только передача, используйте свой, софтовый. Он пишется на раз-два.

тока не отбрасывай её в сторону )))

Случаем, не про это речь?
Проверил. Работает. Но память, конечно, жрёт. Поменьше, но…

Найти эту ногу очень просто. Стандартно в сетапе обьявите скорость (например Serial.begin(9600):wink: Загоняете в цикл например Serial.write(0x21); с delay(1000); берёте USB свисток (USB to Com) и пином Rx тыкаете по порядку на все пины . В мониторе порта смотрите с которого идёт символ ! Вот и весь поиск.