Библиотека Wire.h работает на Uno, но не компилируется для ATtiny85

TL;DR:

  • Ардуино голодны по току, поэтому я хочу переключить свой микроконтроллер
  • код работает на Uno, я меняю загрузку на ATtiny85, код не компилируется
  • Wire.h обрывается на входе TWBR
  • Должен ли я продолжать пытаться исправить это или мне следует просто использовать ATmega328P без Arduino?



Поэтому я работаю над проектом, в котором я отправляю данные с IMU (MPU6050) на телефон с помощью Bluetooth-файла (HC08) с небольшой фильтрацией сигналов с помощью микроконтроллера между ними. Я использовал мини-компьютеры Pro, но потребление тока этими платами просто смешно, поэтому я пытаюсь заменить их некоторыми ATtiny85, которые у меня есть.

Проблема в том, что библиотека Wire.h не будет компилироваться для ATtiny85. Также стоит отметить, что код MPU6050 по умолчанию требует использования контакта прерывания, которого у Attiny's нет, поэтому я изменил код для работы без него (я не уверен, что это часть проблемы).

#include <SoftwareSerial.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#include "Wire.h"

//==============================================================================
// MPU6050 initialization code
MPU6050 mpu;
uint16_t packetSize;
uint16_t fifoCount;
uint8_t fifoBuffer[64];
Quaternion q;
VectorInt16 aa;
VectorInt16 aaReal;
VectorInt16 aaWorld;
VectorFloat gravity;

//==============================================================================
// microcontroller initialization code
int avg_counter = 0;
int pts_to_avg = 15;
int * x_array = (int*)malloc(sizeof(int) * 25);
int * y_array = (int*)malloc(sizeof(int) * 25);
int * z_array = (int*)malloc(sizeof(int) * 25);

//==============================================================================
// HC-08 initialization code
const byte rxPin = 3;
const byte txPin = 4;
SoftwareSerial bleSerial(rxPin, txPin);

//==============================================================================
void setup() {
  // MPU6050 setup code ========================================================
  Wire.begin();
  TWBR = 24;
  mpu.initialize();
  mpu.dmpInitialize();
  mpu.setXAccelOffset(-1343);
  mpu.setYAccelOffset(-1155);
  mpu.setZAccelOffset(1033);
  mpu.setXGyroOffset(19);
  mpu.setYGyroOffset(-27);
  mpu.setZGyroOffset(16);
  mpu.setDMPEnabled(true);
  packetSize = mpu.dmpGetFIFOPacketSize();
  fifoCount = mpu.getFIFOCount();

  // microcontroller setup code ================================================


  // HC-08 setup code ==========================================================
  // make sure your HC-08 is set to the same baud as below!
  bleSerial.begin(19200);
  delay(100);
}

//==============================================================================
void loop() {
  while(fifoCount < packetSize){
    fifoCount = mpu.getFIFOCount();
  }

  if(fifoCount == 1024){
    mpu.resetFIFO();
    bleSerial.println(F("FIFO overflow!"));
  }else{
    if(fifoCount % packetSize != 0){
      mpu.resetFIFO();
    }else{
      while(fifoCount >= packetSize){
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        fifoCount -= packetSize;
      }

      mpu.dmpGetQuaternion(&q,fifoBuffer);
      mpu.dmpGetAccel(&aa, fifoBuffer);
      mpu.dmpGetGravity(&gravity, &q);
      mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
      mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);

      // points are averaged to keep the baud low w/o FIFO overflow
      if(avg_counter <= pts_to_avg){
        // add live data to this array and hold onto it to be averaged
        x_array[avg_counter] = aaWorld.x;
        y_array[avg_counter] = aaWorld.y;
        z_array[avg_counter] = aaWorld.z;
        avg_counter++;
      }else{
        // average data from the array
        int x_average=0;
        int y_average=0;
        int z_average=0;

        // sums the data in #_average
        for(int i = 0; i < avg_counter; i++){
          x_average += x_array[i];
          y_average += y_array[i];
          z_average += z_array[i];
        }

        // divides by avg_counter (which should == pts_to_avg)
        x_average /= avg_counter;
        y_average /= avg_counter;
        z_average /= avg_counter;

        // resets counter so the array data can be overwritten with future data
        avg_counter = 0;

        // prints data to serial port (if BT is connected, sends via BT)
        bleSerial.print(x_average);
        bleSerial.print(",");
        bleSerial.print(y_average);
        bleSerial.print(",");
        bleSerial.println(z_average);
      }
    }
  }
}

При использовании Arduino в качестве поставщика услуг интернета, при выборе "Плата: attiny25/45/85", "Процессор: ATtiny85" и "Часы: Внутренний 1 МГц" появилась следующая ошибка:

exit status 1
'TWBR' was not declared in this scope

эта ошибка не возникла при компиляции для Uno. Если вы закомментируете TWBR, то получите огромное сообщение об ошибке (я вставлю только немного):

In file included from c:\users\auphynne\appdata\local\arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2\avr\include\avr\io.h:99:0,

                 from C:\Users\auPhynne\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\Wire\src\utility\twi.c:25:

C:\Users\auPhynne\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\Wire\src\utility\twi.c:426:15: error: 'TWINT' undeclared (first use in this function)

    TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;

               ^

C:\Users\auPhynne\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\Wire\src\utility\twi.c:426:28: error: 'TWSTA' undeclared (first use in this function)

    TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;

                            ^

C:\Users\auPhynne\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\Wire\src\utility\twi.c:426:40: error: 'TWEN' undeclared (first use in this function)

    TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;

                                        ^

exit status 1
Error compiling for board ATtiny25/45/85.

Чтобы попытаться исправить это, я вошел в

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src\utility\twi.c

и жестко закодировал эту строку из

// initialize twi prescaler and bit rate
cbi(TWSR, TWPS0);
cbi(TWSR, TWPS1);
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;

чтобы

// initialize twi prescaler and bit rate
cbi(TWSR, TWPS0);
cbi(TWSR, TWPS1);
TWBR = 24;

и я все еще получал то же самое ужасное сообщение об ошибке.

Контакты-это то, что вы ожидаете, мощность 5 В как для модулей, так и для заземления, плюс:

  • Uno D4 -> HC08 RXD
  • Uno D3 -> HC08 TXD
  • SCL UNO -> MPU6050 SCL>
  • ПДД UNO -> ПДД MPU6050>

(снова обратите внимание, что вывод прерывания не используется, и это сработало довольно хорошо при построении Uno! У меня есть данные о приложении последовательного терминала BT моего телефона, так что, похоже, это не проблема)

Есть какие-нибудь идеи о том, как я могу заставить Wire.h компилироваться на ATtiny85?

Или... должен ли я просто прерваться и пойти с ATmega328P (без сопровождающего Uno), так как он поставляется в четырехъядерной плоской SMD-упаковке? (след имеет значение в долгосрочной перспективе)

, 👍5

Обсуждение

Если вы действительно хотите свести к минимуму энергопотребление, вам, вероятно, следует подключить датчик непосредственно к пользовательской прошивке на микроконтроллере BTLE без промежуточной части. Вы можете запускать код Arduino на nRF51822, хотя это может быть не самым дешевым программным подходом для него. Кроме того, MEMS - датчик + BTLE-это распространенная демонстрационная версия для компаний, производящих последние, поэтому вы можете найти оборудование, уже изготовленное с помощью рабочего программного обеспечения., @Chris Stratton

Я бы предложил использовать Arduino Pro Mini (и внешний преобразователь USB в последовательный). Они используют тот же ATmega328P, но без дополнительной траты энергии uno. Они также намного меньше. Вы можете внести некоторые изменения в плату, чтобы получить немного больше времени автономной работы, например, удалить индикатор питания., @Gerben

Я получаю ту же ошибку, даже несмотря на то, что я использую<TinyWireM.h>, как и другие библиотеки<Adafruit_BNO055.h>, и <SparkFun_Qwiic_OpenLog_Arduino_Library.h>использую библиотеку Wire.h, и ATtiny85 выдает ошибку во время компиляции. Кто-нибудь может помочь, пожалуйста. Код (просто включение библиотек вызывает ошибку) #включить <SparkFun_Qwiic_OpenLog_Arduino_Library.h>// Регистратор данных #включить <Adafruit_BNO055.h>//IMU #включить <Adafruit_Sensor.h>#включить <TinyWireM.h>#включить <utility/imumaths.h>пустую настройку() { // поместите свой код установки здесь, чтобы запустить один раз: } пустая петля() { // поместите свой основной код здесь, чтобы запустить, @Paramveer


2 ответа


Лучший ответ:

7

Вы получаете эту ошибку, потому что ATtiny85 не имеет полного оборудования I2C. Это только как USI (Универсальный последовательный интерфейс). Это может быть использовано для выполнения остальной части протокола I2C с помощью программного обеспечения. Для этого существует несколько библиотек, большинство из которых называются TinyWire. Были специальные библиотеки для основной и подчиненной работы под названием TinyWireM и TinyWireS. И я составил одну библиотеку с обоими функциональными возможностями (и еще несколькими) в TinyWire. Последний, я думаю, для вас непригоден, потому что библиотеке SoftwareSerial для работы нужен PinChangeInterrupt, но TinyWire использует его для определения условий остановки на шине I2C.

Поэтому для вашего случая вы можете использовать библиотеку TinyWireM. Обратите внимание, что для основных операций требуется точное время. Использование большого количества прерываний в это время может вызвать проблемы в передаче. Проверьте его и отключите прерывания, если это необходимо.

,

Я использую MPU6050 в своем проекте и библиотеку MPU6050.h, которая включает в себя библиотеку I2Cdev.h, которая включает в себя библиотечный провод.h и использует ее много - у меня такое чувство, что этого будет недостаточно, чтобы заменить все экземпляры Wire.foo() на TinyWireM.foo() в библиотеке I2Cdev.h.. ? Библиотека TinyWireM.h абсолютно выглядит как правильное решение, большое вам спасибо, но если ее реализация будет слишком сложной, я не уверен, что у меня хватит навыков программирования, чтобы ее реализовать (в этом случае я просто остановлюсь на ATmegas :l ), @Austin Fennacy

В принципе, библиотека TinyWireM имеет многие из тех же функций, что и библиотека Wire (за исключением подчиненных функций). Но могут возникнуть и другие проблемы, если просто изменить это. Вы можете попробовать изменить его, проще всего было бы использовать Arduino Pro mini (как упоминал Гербен). И если это ответ на ваш вопрос, пожалуйста, отметьте его как правильный :D, @chrisl


2

Если вы хотите, чтобы библиотека Wire.h работала с attiny85, используйте:

https://github.com/SpenceKonde/ATTinyCore

Я сделал это, и он компилируется.

,