Sample code from bq769x0 arduino library does not compile - arduino

I try to use arduino library from github:
https://github.com/LibreSolar/bq769x0-arduino-library/blob/master/bq769x0.h
but it doesn't even compile.
Error is connected with :
#if BQ769X0_DEBUG
void printRegisters(void);
#endif
When I comment it it compiles, but I need this for debuging of course.
I assume, that this is a simple problem, but I have not much experience with programming. Please help.
I tried commenting it, and i think it works, but than i don't see any results in serial monitor

This is called "conditional compilation". If the preprocessor value BQ769X0_DEBUG is defined, then the bq769x0 class member function printRegisters is declared and defined (i.e. it exists). If BQ769X0_DEBUG is not defined, then that function does not exist and trying to call it is an error.
If you want to use that function, define it before including the header:
#define BQ769X0_DEBUG // Enable debug features
#include <bq769x0.h>
bq769x0 BMS(bq76920, BMS_I2C_ADDRESS);
I'm fairly certain this will work on Arduino as AFAIK, it does not pre-compile libraries.
Note, that if you decide to disable the debug features by not defining it:
// #define BQ769X0_DEBUG
#include <bq769x0.h>
bq769x0 BMS(bq76920, BMS_I2C_ADDRESS);
// BMS.printRegisters does not exist!
it will be an error to later call that function. To fix that, you can use code guards in your code:
void loop()
{
BMS.update(); // should be called at least every 250 ms
#ifdef BQ769X0_DEBUG
BMS.printRegisters();
#endif
}
Another option would be to change the library header from:
#if BQ769X0_DEBUG
void printRegisters(void);
#endif
to
#if BQ769X0_DEBUG
void printRegisters(void);
#else
void printRegisters(void) {}
#endif
In this case, when BQ769X0_DEBUG is not defined, the printRegisters function is created but does not do anything. Calling it won't cause an error.
Or, make your own macro:
#ifdef BQ769X0_DEBUG
#define PRINT_REGISTERS BMS.printRegisters()
#else
#define PRINT_REGISTERS
#endif
Then change the usage to:
void loop()
{
BMS.update(); // should be called at least every 250 ms
PRINT_REGISTERS;
}
Note: this macro is hardcoded to use the BMS object. It would need to be modified to use others.

Related

How may I fix my error prone on_foo_bar slots

I have eight list widgets in a tab widget. They have similar names, and Designer's "Go to slot" mechanism has made links to slots it names (in the "private slots" section of "mainwindow.h") like:
void on_SR0listWidget_itemClicked(QListWidgetItem *item);
I saw warnings that "Slots named on_foo_bar are error-prone," and now I need to change their names in order to discover if that's the cause of the weird behaviour I'm getting.
I tried simply refactoring the names, but that stopped the slot code from working. I used Designer's graphical "Edit Signal/Slot" mechanism and was able to connect a newly added list widget's "itemClicked(QListWidgetItem *item)" signal to a newly added slot, and it looks OK in the graphical representation, but there's no debug message (that I set up in the Slot function) when an item is clicked.
I also use those widgets' "entered" signals, so there will be at least 16 to fix. I would write a script if it could be done by parsing the relevant files.
One example of exactly how to rename one of my replacement slots and connect an "item clicked" or "entered" signal to it (and where it should go) would be a great help.
Signals/slots setup through the designer rely on the names of the widgets involved. This can lead to problems if the widget names are changed. There are times when using the designer method will lead to code that compiles but doesn't actually make the connections you expect. This is why you are getting that warning.
You can get more reliable behavior by connecting the signals and slots programmatically. For example, let's say you have a class header such as:
#include <QMainWindow>
namespace Ui {
class MyWindow;
};
class QListWidgetItem;
class MyWindow : public QMainWindow {
Q_OBJECT
public:
explicit MyWindow(QWidget* parent = nullptr);
~MyWindow() override;
private:
void handleItemClicked(QListWidgetItem* item); // this is your slot
Ui::MyWindow* ui;
};
You can connect the signal/slot together in the cpp file like this:
#include "MyWindow.h"
#include "ui_MyWindow.h"
#include <QDebug>
MyWindow::MyWindow(QWidget* parent)
: QWidget(parent),
ui(new Ui::MyWindow()) {
ui->setupUi(this);
// connect() has many overloads, but in this case we are passing:
// 1. the object emitting the signal
// 2. the signal being emitted
// 3. the object whose slot we want to call
// 4. the slot to connect to
connect(
ui->listWidget, &QListWidget::itemClicked,
this, &MyWindow::handleItemClicked);
}
MyWindow::~MyWindow() {
delete ui;
}
void MyWindow::handleItemClicked(QListWidgetItem* item) {
qDebug() << "item clicked";
}
You can still use the designer to layout your UI - but prefer to manage connections directly in code rather than through the designer.

Can't figure out how or why this code solves an error. ESP32 arduino IDE with platform dot io

I am fairly new to coding and especially to C++ but usually with enough googling and breaking problems down to simpler blocks I can figure things out. This issue makes no sense to me though and the solution I just happened to come up with on accident makes even less sense to me.
I am writing a program for ESP32-S in vscode with platformio and broke this down to isolate what was causing the error and found this issue with class/object declaration:
This code will compile but I get a link error twice that says
undefined reference to `point::point()'
#include <Arduino.h>
class point {
public:
point();
point(uint day){
this->_day = day;
}
uint _day;
};
class channel {
public:
channel(String _color, byte _pin){
}
point _points[64];
};
channel red("red", 0);
void setup() {}
void loop() {}
Meanwhile this code with one seemingly unrelated change compiles and links without issue:
#include <Arduino.h>
class point {
public:
point();
point(uint day){
this->_day = day;
}
uint _day;
};
class channel {
public:
channel(){ // <--- Removing the arguments from channel constructor fixes it?
}
point _points[64];
};
channel red(); // <--- And here of course
void setup() {}
void loop() {}
I don't know why that fixes it, and I have a workaround for now if this is what I have to do, but I want to understand. Thanks.
You've declared a constructor point::point(), but not defined it (i.e. it has no body). This is not OK with the linker and that's what you're being told.
There are three ways to fix this.
Don't declare the constructor (compiler generates a default constructor which may or may not initialize the member _day to 0, depending on compiler and platform). Note that you also have the interesting alternative of deleting the default constructor.
Declare and define it to do whatever you consider appropriate.
Give your constructor point::point(uint day) a default argument value, e.g.: point::point(uint day = 0).
Side note on C style arrays of C++ objects like here:
point _points[64];
This is a dangerous combination, unless you know exactly what you're doing. See the C++ FAQ

Get UID from NFC Card on ESP32

I am having a bit of trouble reading an NFC card with an ESP32 (using Arduino IDE). I'm using PN532 module, which works pretty well. So far my code looks like:
#include <SPI.h>
#include <PN532_SPI.h>
#include <PN532.h>
#include <NfcAdapter.h>
PN532_SPI pn532spi(SPI, SS);
NfcAdapter nfc = NfcAdapter(pn532spi);
void setup(void) {
Serial.begin(115200);
Serial.println("NDEF Reader");
nfc.begin();
}
void loop(void) {
//Serial.println("\nScan a NFC tag\n");
if (! nfc.tagPresent())
{
return;}
else{
NfcTag tag = nfc.read();
String scannedUID = tag.getUidString();
Serial.println(scannedUID);
}
delay(5000);
}
which is basically just the example from don's ndef library. I just got the UID string, rather than printing all details of the card.
It does work and displays the UID. However, I get a message saying "Tag is not NDEF formatted". Which I don't really care about. I only want to print the UID to serial and then pick this up in a C# windows app. I guess I could just ignore it, but is there a way to stop it showing up?
Is there a better library I should be using?
Thanks
Andrew
I fixed it by modifying the mifareclassic.cpp file which is part of the library. I just commented out the offending line. Probably a better way since it's still doing the check. But will do for now.
Thanks
Andrew

Why won't C++/WinRT IDL file allow me to define a method with a pointer as a parameter?

I am using code in a C# UWP project to generate data in a short array, pass this data to code in a C++/WinRT Component project (using a pointer and the array's length), modify the data, and then pass back a new array (using a pointer and the array's length) to the C# code. Using the code below, I do not immediately get errors. However, building the C++/WinRT project fails, as my idl file gets the error: MIDL2025 [msg]syntax error [context]: expecting an identifier near "*".
Is it possible to pass pointers from C# to C++/WinRT? (If you see any additional issues with my code or its efficiency, feel free to let me know.)
I have scoured the internet for all information regarding C++/WinRT (not C++/CX) and .idl files. I do not think anything more than a few years old will be accurate for C++/WinRT. C++/WinRT was released on June 23, 2015 and anything before then regarding WinRT will really just be C++/CX. I made my code by following the example here: https://github.com/microsoft/Windows-appsample-photo-editor/blob/master/PhotoEditor/Photo.idl. Also, I believe that the idl files in C++/WinRT are actually MIDL 3.0. Looking at this link https://learn.microsoft.com/en-us/uwp/midl-3/intro#types, I changed my idl file to accept Int32 rather than int and Int16* rather than short* (please let me know if that is unnecessary). I have researched a bit about the out keyword, but it did not seem to work with MIDL 3.0. To be clear I want to get back short* as in the pointer, not short as in the value.
Here is my idl file:
//.idl file
namespace MyNamespace
{
[default_interface]
runtimeclass MyClass
{
MyClass();
void DoStuff(Int32 length, Int16* inbuf, Int16* outbuf);
}
}
Here is my header file:
//.h file
#pragma once
#include "MyClass.g.h"
namespace winrt::MyProject::implementation
{
struct MyClass: MyClassT<MyClass>
{
MyClass() = default;
void DoStuff(int length, short* inbuf, short* outbuf);
};
}
namespace winrt::MyProject::factory_implementation
{
struct MyClass: MyClassT<MyClass, implementation::MyClass>
{
};
}
Here is my C++ file:
//.cpp file
#include "pch.h"
#include "MyClass.h"
#include "MyClass.g.cpp"
namespace winrt::MyProject::implementation
{
void MyClass::DoStuff(int length, short* inbuf, short* outbuf)
{
//Process data here by editing outbuf
}
}
Thank you in advance!

Unexpected behavior when using freeRTOS with two tasks

I am using MPU9250-breakout board with Arduino Uno.
The library I used is from here.
Below is my code.
#include <Arduino_FreeRTOS.h>
#include "mpu9250.h"
MPU9250 IMU(Wire,0x68);
int status;
void task_1(void *pvParameters)
{
(void) pvParameters;
for (;;)
{
}
}
void task_2(void *pvParameters)
{
(void) pvParameters;
for (;;)
{
}
}
void setup() {
Serial.begin(115200);
while(!Serial) {}
status = IMU.begin();
if (status < 0) {
Serial.println("IMU initialization unsuccessful");
Serial.println("Check IMU wiring or try cycling power");
Serial.print("Status: ");
Serial.println(status);
while(1) {}
}
xTaskCreate(
task_2,
(const portCHAR *)"task2", // A name just for humans
128, // Stack size
NULL,
1, // priority
NULL);
xTaskCreate(
task_1,
(const portCHAR *)"task1", // A name just for humans
128, // Stack size
NULL,
1, // priority
NULL);
}
void loop()
{
}
The problem is that when there are two tasks defined, the program will be restarted automatically. But when I comment out task_1, the program works fine. The result value of xTaskCreate is correct.
I guess the problem might be the stack or heap size is too small, but I've increased stack and heap size and it's still doesn't work.
Can anyone tell me where the problem might be from?
At the end of your setup(), you need to start the scheduler:
// Now the task scheduler, which takes over control of scheduling individual tasks, //is automatically started.
vTaskStartScheduler();
That is all I see different between my project which works and yours.
Once you have created your tasks, you have to start scheduler.
Call vTaskStartScheduler() before exiting setup function and after you have created your tasks.
https://www.freertos.org/a00132.html
Just for the info, Arduino-UNO (with ATMega-328P) has very limited RAM and it may happen some tasks won't be created. Check return value of xTaskCreate functions.
When I run into this problem, it's usually been that my interrupt vectors weren't pointing to appropriate handlers. So when the RTOS needed to do a context switch, for example, it jumped off into la-la land. Since you say that taking out the tasks allows it to run to the library call, but fails in the same way, it is possible none of your handlers are setup correctly.
The FreeRTOS website has an FAQ about getting new projects to run that I would suggest reading through to help troubleshoot this kind of problem:
https://www.freertos.org/FAQHelp.html#faq
You might also look at some of the other AVR examples included with FreeRTOS to see how they have interrupts setup: https://www.freertos.org/a00090.html#ATMEL

Resources