Создание библиотеки для ардуино
Я нашел действительно хороший 24-битный АЦП I2C, который к тому же был довольно дешевым (ADS1219), но, насколько я мог судить, для него нет библиотек, поэтому я решил сделать свою собственную. Мне удалось написать функции и заставить все работать на самой Arduino, но у меня возникли серьезные проблемы с преобразованием их в библиотеку. Итак, я попробовал сделать очень простой скетч, чтобы посмотреть, смогу ли я сделать что-то простое, например, напечатать hello world, используя библиотеку. Вот мой файл ADS1219.h:
#ifndef ADS1219
#define ADS1219
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
class ADS1219{
public:
ADS1219();
void begin();
void printHello();
};
#endif
И ADS1219.cpp:
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include
ADS1219::ADS1219{
Serial.println("New object created!");
}
void ADS1219::begin(){
Serial.begin(9600);
}
void ADS1219::printHello(){
Serial.println("Hello World");
}
и мой основной набросок:
#include
ads = new ADS1219;
void setup() {
Serial.begin(9600);
ads.begin();
}
void loop() {
ads.printHello();
delay(2000);
}
но я получаю очень длинную ошибку, которая, по сути, говорит о том, что мне не удалось создать объект a ds. Я попробовал рекламу ADS1219; тоже, но та же ошибка... не знаю, в чем дело, если честно.
Arduino: 1.8.8 (Windows 10), Board: "Arduino Nano, ATmega328P (Old Bootloader)"
In file included from sketchADS1219.cpp:7:0:
ADS1219.h:14:11: error: expected unqualified-id before ')' token
ADS1219();
^
ADS1219.h:12:14: error: an anonymous struct cannot have function members
class ADS1219{
^
ADS1219.h:18:1: error: abstract declarator '' used as declaration
};
^
ADS1219.cpp:9:17: error: expected id-expression before '{' token
ADS1219::ADS1219{
^
ADS1219.cpp:13:21: error: explicit qualification in declaration of 'void begin()'
void ADS1219::begin(){
^
ADS1219.cpp:17:26: error: explicit qualification in declaration of 'void printHello()'
void ADS1219::printHello(){
^
In file included from C:UsersOM222ODesktopadslibadslib.ino:1:0:
ADS1219.h:14:11: error: expected unqualified-id before ')' token
ADS1219();
^
ADS1219.h:12:14: error: an anonymous struct cannot have function members
class ADS1219{
^
ADS1219.h:18:1: error: abstract declarator '' used as declaration
};
^
adslib:3:1: error: 'ads' does not name a type
ads = new ADS1219;
^
C:UsersOM222ODesktopadslibadslib.ino: In function 'void setup()':
adslib:7:3: error: 'ads' was not declared in this scope
ads.begin();
^
C:UsersOM222ODesktopadslibadslib.ino: In function 'void loop()':
adslib:11:3: error: 'ads' was not declared in this scope
ads.printHello();
^
exit status 1
expected unqualified-id before ')' token
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
@OM222O, 👍0
Обсуждение3 ответа
Ваша проблема связана с этой строкой:
#define ADS1219
Вы определяете макрос ADS1219 как пустой. С этого момента все ссылки на ADS1219 ничем не заменяются. Например:
class ADS1219{
public:
ADS1219();
void begin();
void printHello();
};
становится:
class {
public:
();
void begin();
void printHello();
};
И
void ADS1219::begin(){
Serial.begin(9600);
}
становится:
void ::begin(){
Serial.begin(9600);
}
Используя в заголовке то же имя, что и имя класса, вы портите все остальное.
Я всегда использую строгие правила для макросов защиты заголовков, чтобы гарантировать, что они никогда не конфликтуют ни с чем другим. Вам следует изменить свое, чтобы прочитать что-то другое. Я бы использовал:
#ifndef _ADS1219_H
#define _ADS1219_H
// ... содержание
#endif
В реализации конструктора также отсутствуют круглые скобки:
ADS1219::ADS1219{
Serial.println("New object created!");
}
следует читать:
ADS1219::ADS1219(){
Serial.println("New object created!");
}
И вы не задаете тип переменной ads
и не хотите использовать new:
ads = new ADS1219;
следует читать:
ADS1219 ads;
Также в файл cpp ему не следует снова включать файл Arduino.h, а включать только файл библиотеки (ADS1219.h). Более того, в свои библиотеки я перестал включать WProgram.h. Вы считаете, что это все еще необходимо?, @frarugi87
Я не включал wprogram.h целую вечность. Не помешает включить файл несколько раз, поскольку заголовки должны включать защиту заголовков., @Majenko
спасибо, это решило мою проблему на данный момент: DI попытаюсь закончить остальное самостоятельно, но мне все равно может понадобиться помощь. Я опубликую ее, как только закончу, @OM222O
Вы уверены, что компилируете это для C++, а не C?
В любом случае вы определяете
#define ADS1219
Я не знаю, как это повлияет на имя вашего класса. Вы пробовали
#define ADS1219_H // <- Стандартное включение защиты
вместо этого? Дает ли это разные результаты?
arduino — это сам C, но расширение файла — cpp (c plus plus), поэтому я сам немного запутался. Изменение его на ADS1219_H приводит к тому же сообщению об ошибке., @OM222O
спасибо за указание на это, и да, я использую IDE. Я почти уверен, что он использует компоновщик GCC и уже настроен правильно., @OM222O
Standard include Guard
- разве не для этого используется #pragma Once
?, @Jaromanda X
Arduino — это C++, а не C., @Majenko
Я добился большого прогресса и почти все работает нормально... за исключением того, что я изначально использовал струны в корпусе переключателя для настройки режимов опорного напряжения и преобразования... это совсем не понравилось. Вместо этого я намеревался использовать перечисления для той же цели, но теперь получаю следующую ошибку:
Arduino: 1.8.8 (Windows 10), Board: "Arduino Nano, ATmega328P (Old Bootloader)"
In file included from sketch\LibraryExample1.ino.cpp:1:0:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:81:18: error: expected identifier before numeric constant
#define INTERNAL 3
^
C:\Users\OM222O\Documents\Arduino\libraries\ADS1219/ADS1219.h:49:3: note: in expansion of macro 'INTERNAL'
INTERNAL = VREF_INTERNAL,
^
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:81:18: error: expected '}' before numeric constant
#define INTERNAL 3
^
C:\Users\OM222O\Documents\Arduino\libraries\ADS1219/ADS1219.h:49:3: note: in expansion of macro 'INTERNAL'
INTERNAL = VREF_INTERNAL,
^
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:81:18: error: expected unqualified-id before numeric constant
#define INTERNAL 3
^
C:\Users\OM222O\Documents\Arduino\libraries\ADS1219/ADS1219.h:49:3: note: in expansion of macro 'INTERNAL'
INTERNAL = VREF_INTERNAL,
^
In file included from C:\Users\OM222O\Desktop\LibraryExample1\LibraryExample1.ino:2:0:
C:\Users\OM222O\Documents\Arduino\libraries\ADS1219/ADS1219.h:51:1: error: expected declaration before '}' token
}adsRef_t;
^
exit status 1
Error compiling for board Arduino Nano.
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
мой файл ADS1219.h:
#ifndef ADS1219_H
#define ADS1219_H
#if (ARDUINO >=100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <Wire.h>
#define CONFIG_REGISTER_ADDRESS 0x20
#define STATUS_REGISTER_ADDRESS 0x24
#define MUX_MASK 0x1F
#define MUX_DIFF_0_1 0x00
#define MUX_DIFF_2_3 0x20
#define MUX_DIFF_1_2 0x40
#define MUX_SINGLE_0 0x60
#define MUX_SINGLE_1 0x80
#define MUX_SINGLE_2 0xA0
#define MUX_SINGLE_3 0xC0
#define MUX_SHORTED 0xE0
#define GAIN_MASK 0xEF
#define GAIN_ONE 0x00
#define GAIN_FOUR 0x10
#define DATA_RATE_MASK 0xF3
#define DATA_RATE_20 0x00
#define DATA_RATE_90 0x04
#define DATA_RATE_330 0x08
#define DATA_RATE_1000 0x0c
#define MODE_MASK 0xFD
#define MODE_SINGLE_SHOT 0x00
#define MODE_CONTINUOUS 0x02
#define VREF_MASK 0xFE
#define VREF_INTERNAL 0x00
#define VREF_EXTERNAL 0x01
typedef enum{
ONE = GAIN_ONE,
FOUR = GAIN_FOUR
}adsGain_t;
typedef enum{
INTERNAL = VREF_INTERNAL,
EXTERNAL = VREF_EXTERNAL
}adsRef_t;
typedef enum{
SINGLE_SHOT = MODE_SINGLE_SHOT,
CONTINUOUS = MODE_CONTINUOUS
}adsMode_t;
class ADS1219 {
protected:
uint8_t address;
public:
// Constructor
ADS1219(int drdy, uint8_t addr = 0x40);
// Methods
void begin();
void resetConfig();
long readSingleEnded(int channel);
long readDifferential_0_1();
long readDifferential_2_3();
long readDifferential_1_2();
long readShorted();
void setGain(adsGain_t gain);
void setDataRate(int rate);
void setConversionMode(adsMode_t mode);
void setVoltageReference(adsRef_t vref);
private:
void writeRegister(uint8_t data);
uint8_t readRegister(uint8_t reg);
long readConversionResult();
uint8_t config;
int data_ready;
};
#endif
и мой файл cpp:
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <Wire.h>
#include "ADS1219.h"
static uint8_t i2cRead(void) {
#if ARDUINO >= 100
return Wire.read();
#else
return Wire.receive();
#endif
}
static void i2cWrite(uint8_t x) {
#if ARDUINO >= 100
Wire.write(x);
#else
Wire.send(x);
#endif
}
ADS1219::ADS1219(int drdy, uint8_t addr) {
data_ready = drdy;
address = addr;
config = 0x00;
}
void ADS1219::begin() {
Wire.begin();
}
uint8_t ADS1219::readRegister(uint8_t reg){
Wire.beginTransmission(address);
i2cWrite(reg);
Wire.endTransmission();
Wire.requestFrom((uint8_t)address,(uint8_t)1);
return i2cRead();
}
void ADS1219::writeRegister(uint8_t data){
Wire.beginTransmission(address);
i2cWrite(CONFIG_REGISTER_ADDRESS);
i2cWrite(data);
Wire.endTransmission();
}
long ADS1219::readConversionResult(){
Wire.beginTransmission(address);
i2cWrite(0x10);
Wire.endTransmission();
Wire.requestFrom((uint8_t)address,(uint8_t)3);
byte dataMSB = i2cRead();
byte data = i2cRead();
byte dataLSB = i2cRead();
long data32 = dataMSB;
data32 <<= 8;
data32 |= data;
data32 <<= 8;
data32 |= dataLSB;
return (data32 << 8) >> 8;
}
void ADS1219::resetConfig(){
writeRegister(0x00);
}
long ADS1219::readSingleEnded(int channel){
if (channel > 3) return 0;
config &= MUX_MASK;
switch (channel){
case (0):
config |= MUX_SINGLE_0;
break;
case (1):
config |= MUX_SINGLE_1;
break;
case (2):
config |= MUX_SINGLE_2;
break;
case (3):
config |= MUX_SINGLE_3;
break;
default:
break;
}
writeRegister(config);
while(digitalRead(data_ready)==1);
return readConversionResult();
}
long ADS1219::readDifferential_0_1(){
config &= MUX_MASK;
config |= MUX_DIFF_0_1;
writeRegister(config);
while(digitalRead(data_ready)==1);
return readConversionResult();
}
long ADS1219::readDifferential_2_3(){
config &= MUX_MASK;
config |= MUX_DIFF_2_3;
writeRegister(config);
while(digitalRead(data_ready)==1);
return readConversionResult();
}
long ADS1219::readDifferential_1_2(){
config &= MUX_MASK;
config |= MUX_DIFF_1_2;
writeRegister(config);
while(digitalRead(data_ready)==1);
return readConversionResult();
}
long ADS1219::readShorted(){
config &= MUX_MASK;
config |= MUX_SHORTED;
writeRegister(config);
while(digitalRead(data_ready)==1);
return readConversionResult();
}
void ADS1219::setGain(adsGain_t gain){
config &= GAIN_MASK;
config |= gain;
writeRegister(config);
}
void ADS1219::setDataRate(int rate){
config &= DATA_RATE_MASK;
switch (rate){
case (20):
config |= DATA_RATE_20;
break;
case (90):
config |= DATA_RATE_90;
break;
case (330):
config |= DATA_RATE_330;
break;
case (1000):
config |= DATA_RATE_1000;
break;
default:
break;
}
writeRegister(config);
}
void ADS1219::setConversionMode(adsMode_t mode){
config &= MODE_MASK;
config |= mode;
writeRegister(config);
}
void ADS1219::setVoltageReference(adsRef_t vref){
config &= VREF_MASK;
config |= vref;
writeRegister(config);
}
Кажется, он передает Gain (или, возможно, еще не скомпилировал его), но не может выбрать ссылку... Я не знаю, что мне следует изменить, чтобы решить проблему.
Редактировать: я очень надеюсь, что это не очередное соглашение об именах... если это так, то извините, но C++, похоже, слишком требователен к именам в целом
Подсказка: используйте частное перечисление для всех управляющих кодов и т. д. Использование #define — это старая школа, которая на самом деле является основной причиной многих проблем. C++ допускает пространства имен, частные, константные и т. д., что гораздо более семантически богато. Вот пример, который поможет вам в этом; https://github.com/mikaelpatel/Cosa/blob/master/libraries/ADXL345/ADXL345.hh, @Mikael Patel
Подсказка: чтобы избежать использования некоторых констант, масок и т. д., в структурах можно использовать битовые поля. Вот пример: https://github.com/mikaelpatel/Cosa/blob/master/libraries/DS2482/DS2482.hh, @Mikael Patel
большое спасибо! Я посмотрю. Я почти закончил программу :D, @OM222O
- Какие Arduino поддерживают ATOMIC_BLOCK?
- Как запрограммировать ардуино на чистом C/C++?
- RtcDateTime' не называет тип
- как отправить аргумент объектам ESP8266WebServer в функции
- GSM-модуль IOT-GA6 Arduino + ошибка CME 58
- Разница между массивом char и массивом unsigned char
- Не могу использовать uint16_t в библиотеке
- Как объединить два значения в строку?
Извините, я не знал, что такое существует... существует так много разных SE, ха-ха-ха. Я перенесу его туда., @OM222O
Первая ошибка: «#define ADS1219». Вместо этого используйте соглашение «#define ADS1219_H». Пожалуйста, возвращайтесь за дополнительной помощью по C++ :)., @Mikael Patel
Это абсолютно ничего не изменило :D, @OM222O
Я даже пытался загрузить точный код для создания библиотек, который показывали некоторые люди, но мне все равно не удалось! буквально тот же код не хочет работать на моей машине! Есть идеи, что я могу делать неправильно? изменить: вот ссылка, по которой я перешел: https://www.alanzucconi.com/2016/05/11/libraries-for-arduino/, @OM222O
Вам не нужно проверять старую версию Arduino. Это больше не используется. На дворе почти 2019 год. Просто подключите Arduino.h (только в файле ADS1219.h). Что такое
#include
без указания, какой файл включать? В скетче достаточно «ads ADS1219». В Github полно библиотек Arduino, там можно найти множество примеров, например: https://github.com/Locoduino/SlowMotionServo/tree/master/src и https://github.com/winlinvip/SimpleDHT (всего два случайных выбранные библиотеки, их должно быть сотни)., @Jot@Jot, это именно то, что я сделал, поэтому у меня даже есть строка для проверки версий Arduino ... Я не знаю, что такое версия 1, но я напрямую скопировал эту часть заголовка из других библиотек. Как я уже сказал, я напрямую копирую чужой код и смотрю, где он ломается, пока не научусь писать все с нуля :D, @OM222O
Я создал здесь точно такой же вопрос... и не могу его удалить... может ли это сделать кто-нибудь другой? Я не хочу спамить вопросами, @OM222O
Кажется, я запутался со слиянием двух вопросов. Теперь это активный вариант., @Nick Gammon
@ OM222O OM222O, ты смотрел эти два случайных примера? Разница между ними и вашим кодом в том, что не так. Мы рассказали вам все, чтобы все заработало. Исправьте определение, исправьте включения, добавьте «()» для конструктора, удалите «= new» для объявления. Вот и все, тогда все будет работать., @Jot