Giter Site home page Giter Site logo

circularbuffer's People

Contributors

abhaybd avatar erlkoenig90 avatar eto- avatar famzah avatar koryphon avatar n-gineer avatar per1234 avatar rlogiacco avatar skleeschulte avatar vpericoli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

circularbuffer's Issues

Can't use library within a class.

Hi.
I am trying to use this library as an object within a class and I am getting the following error:

error: use of deleted function 'constexpr CircularBuffer<timeTempStruct, 10u>::CircularBuffer(const CircularBuffer<timeTempStruct, 10u>&)'

The class is globally instanced as:

className objectName[8] = className (constructor arguments);

Any tip on how to make this work?
Thanks!

Regards!
Gonzalo

How to use these in an array?

I would like to store a number of buffers, and access them anonymously through the array. However, I cannot find a way to do this...

What I expected to be able to do:

CircularBuffer<int, 10> keyboardBuffers[] = {
  CircularBuffer<int,10>(),
  CircularBuffer<int,10>(),
  CircularBuffer<int,10>()
}

keyboardBuffers[0][0];

But this results in:

error: use of deleted function 'CircularBuffer<T, S, IT>::CircularBuffer(CircularBuffer<T, S, IT>&&) [with T = int; unsigned int S = 10; IT = unsigned char]'
 }
 ^
libraries/CircularBuffer/CircularBuffer.h:59:2: note: declared here
  CircularBuffer(CircularBuffer&&) = delete;
  ^~~~~~~~~~~~~~

So I tried using pointers:

CircularBuffer<int, 10>* keyboardBuffers[] = {
  &CircularBuffer<int,10>(),
  &CircularBuffer<int,10>(),
  &CircularBuffer<int,10>()
};

keyboardBuffers[0]->size();

But this results in

error: 'keyboardBuffers' does not name a type
 keyboardBuffers[0]->size();
 ^~~~~~~~~~~~~~~

Can anybody tell me how to use this class in an array in such a way I can access the array subset operator [<index>]?
Thanks!

Passing elements of non-fundamental type by reference

First of all, thank you for this library. It has been very useful.

I have a fork which allows the user (or the compiler) to choose whether to pass elements to push() and unshift() by value or reference. The choice is controlled by a #define:

/**
 * For the push() and unshift() functions, you may choose whether to pass-by-value, pass-by-reference,
 * or have the template choose at compile time based on the element type. This is the default and in this case
 * we pass-by-value for fundamental types and pass-by-reference otherwise. To always use pass-by-value, which
 * is what the original library did, #define ARG_TYPE_VAL *before* including CircularBuffer.h. To always
 * use pass-by-reference #define ARG_TYPE_REF. Don't define either to get the default behavior.
 */
#include <type_traits>
template<typename T>
#if defined(ARG_TYPE_VAL)
	using choose_arg_type = T;
#elif defined(ARG_TYPE_REF)
	using choose_arg_type = const T &;
#else
	using choose_arg_type = typename std::conditional<std::is_fundamental<T>::value, T,  const T&>::type;
#endif

The functions then look like this:

/**
 * Adds an element to the beginning of buffer: the operation returns `false` if the addition caused overwriting an existing element.
 */
bool unshift(choose_arg_type<T> value);

/**
 * Adds an element to the end of buffer: the operation returns `false` if the addition caused overwriting an existing element.
 */
bool push(choose_arg_type<T> value);

I have also added a peekAt():

	/**
	 * Similar to operator [], but returns a const ref to the stored element rather than a copy.
	 * Similar to std::vector::at, but always returns a const reference. 
	 * Calling this operation using and index value greater than `size - 1` returns the tail element.
	 * *WARNING* Calling this operation on an empty buffer has an unpredictable behaviour.
	 */
	const T& peekAt(IT index) const;

Not very useful for fundamental types, but can be useful for larger objects.

I'm happy to pass along the source or create a pull request if you're interested.

Reading data in the historical order

First of all, neat library, thank you!

Do I understand correctly that currently, it is impossible to read values in the order, as they were added (without removing them from the buffer)? For example, if I log sensor values and then want to display them on a chart, I should read them from the most recent ones to the oldest.

Theoretically, it can work in this way:

template <typename T, size_t S, typename IT>
void inline CircularBuffer<T, S, IT>::iterate(void (*callback)(T value))
{
	T *addr = tail;
	while (1)
	{
		callback(*addr);

		if (addr == head)
			break;

		*addr--;
		if (addr < buffer)
		{
			addr = buffer + capacity - 1;
		}
	}
}

But I'm not sure that everything is 100% correct, as the library uses more complicated code than I usually write on C++.

Do you think that adding such an iterator is useful?

Can't use a CircularBuffer of structs?

I'm new to structs, and it probably simply isn't supported, but I'm trying to use a CircularBuffer for some button-press structs, and get the error:

no matching function for call to 'CircularBuffer<volatile buttonPresses, 10u>::push(buttonPress*)'

my code is:

typedef struct buttonPresses
{
  byte button;
  int time; 
} buttonPress;

#include <CircularBuffer.h>
#define CIRCULAR_BUFFER_INT_SAFE
CircularBuffer<volatile buttonPress, 10> pressesBuffer;


void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

  buttonPress foo = { 123, millis() };
  pressesBuffer.push( &foo );

}

Add range-loop based iterators

Any chance of adding compatibility for c++11 range loops?

Id like to be able to iterate over the data using

for (auto & item : cirBuffer ) 
{
...
}

thanks

Circular Buffer requires declarion as ino global

Roberto has been helping me with my use of CB. After many tries (and great support from Roberto) I located the issue was I was having trying to use CB within a class. It seems that CB only links properly if declared globally in the .ino file. When I used extren in the class to reference CB all worked (linked) well.
I'm not sure that a code change is necessary, but it would be good to have a heads up in the documentation. It would have saved Roberto a lot of aggravation time with my issue.

Issue or Design Decision?

The dumpBuf_byVal method logs the wrong values. Did you deliberately omit copy and assignment in the code because people probably won't use it, or do you think it's inappropriate to have these methods?

#include <CircularBuffer.h>

const int N = 5;
CircularBuffer<float, N> buf;

void dumpBuf_byVal( CircularBuffer<float, N> buf ){
  for ( int i = 0; i < buf.size(); i++ ){
    Serial.print(buf[i]);
    Serial.print(" ");
  }
  Serial.println();
  Serial.flush();
}

void dumpBuf_byRef( CircularBuffer<float, N> &buf ){
  for ( int i = 0; i < buf.size(); i++ ){
    Serial.print(buf[i]);
    Serial.print(" ");
  }
  Serial.println();
  Serial.flush();
}

void setup() {
  Serial.begin(9600);
  float f= 1.0;
  for( int i = 0; i < N; ++i ){
    buf.push(f);
  }
  dumpBuf_byVal( buf );
  dumpBuf_byRef( buf );
}

void loop() {
  // put your main code here, to run repeatedly:
}

Is the memset in clear() necessary?

Hello!

I've been working on a project using this library and noticed that the clear() function seemed to be taking an inordinately long time on my microcontroller. I did a little digging, and the culprit seems to be this line below, where you use memset() to erase all the data in the buffer:

memset(buffer, 0, sizeof(buffer));

Since that function sets the head, tail, and count variables, my suspicion was that this memset isn't actually required. The constructors seem to confirm this since they don't memset the buffer on creation (unless it gets initialized to 0 some other way I'm not seeing).

I went ahead and tested this out and everything seems to work great on my project at least, so I wanted to drop you a message and let you know in case this is a nice low-hanging fruit speedup. If I'm wrong and that is important, then that'd be good to know too so I don't end up hitting some sneaky bug later on.

Love the library, btw! Thanks for writing it, it's saved me a lot of time

Thanks, Charlie

I need the address of the array. How can I get the address of an array?

I set a pointer to fetch the address value of the buffer, and put the address value of the buffer. However, I get the following error:
"The expression must be an lvalue or function specifier"

in code:

CircularBuffer<char, 10> chars;
char* pGet = NULL;

void loop()
{
    pGet = &chars[0];
}

How can I get the address value of the buffer?

I tried changing the code as follows, but it also failed. :

pGet = &chars;

License issue / question

Hi,
First of all i want to thank you for this amazing library. I'm using it for a project and it's just perfect! I really love it!

I have only a question about licensing. It seems that there is a conflict between three different tipe of licenses.

In the license file it is stated that the repo is under Apache-2.0 license:

Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

But in the code file it seems to be under full copyright:

CircularBuffer.tpp - Circular buffer library for Arduino.
Copyright (c) 2017 Roberto Lo Giacco. All right reserved.

And soon after under LGPL 2.3 or later:

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

So i wanted to ask you to clarify this, is the library under full copyright, Apache 2.0 or LGPL 2.3?

Thank you!! ๐Ÿ˜ƒ

Fills the whole buffer with first value

I'm having the problem that when I push the first value to the buffer, the whole buffer consists of this value instead of only at one position
As an example

byte ID = 3;
..
buffer_1.push(ID);

gives
buffer_1[0]->3
buffer_1[1]->3
buffer_1[2]->3

CircularBuffer<byte, 3> buffer_1;

bug:Memory trample

When the capacity is set to 0, memory will stampede when pushing data:

CircularBuffer<MsgInfo,0> m_ring_msg_priority_low;
m_ring_msg_priority_low.push(msg);

short = byte?

is short type on your library equate to byte type on arduino?

as in 8 unsigned bit

error: 'CircularBuffer' does not name a type; did you mean 'CellularBase'?

Hi,
i'm trying to run example CircularBuffer.ino from example folder of CircularBuffer Library. I installed 1.3.3 version with Libreries Manager, and i'm using arduino ide 1.8.12
I'm struggling to understand and to solve the following compiling error:

error: 'CircularBuffer' does not name a type; did you mean 'CellularBase'?

Following, i report the complete error message:

CircularBuffer:3:1: error: 'CircularBuffer' does not name a type; did you mean 'CellularBase'?

 CircularBuffer<int, 400> buffer;

 ^~~~~~~~~~~~~~

 CellularBase

CircularBuffer:5:15: error: 'long unsigned int time' redeclared as different kind of symbol

 unsigned long time = 0;

               ^~~~

In file included from c:\users\andrea\appdata\local\arduino15\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4\arm-none-eabi\include\string.h:10:0,

                 from C:\Users\Andrea\AppData\Local\Arduino15\packages\arduino\hardware\mbed\1.1.4\cores\arduino/mbed/platform/Callback.h:20,

                 from C:\Users\Andrea\AppData\Local\Arduino15\packages\arduino\hardware\mbed\1.1.4\cores\arduino/mbed/rtos/Thread.h:29,

                 from C:\Users\Andrea\AppData\Local\Arduino15\packages\arduino\hardware\mbed\1.1.4\cores\arduino/mbed/rtos/rtos.h:28,

                 from C:\Users\Andrea\AppData\Local\Arduino15\packages\arduino\hardware\mbed\1.1.4\cores\arduino/mbed/mbed.h:23,

                 from C:\Users\Andrea\AppData\Local\Arduino15\packages\arduino\hardware\mbed\1.1.4\cores\arduino/Arduino.h:32,

                 from C:\Users\Andrea\AppData\Local\Temp\arduino_build_776870\sketch\CircularBuffer.ino.cpp:1:

c:\users\andrea\appdata\local\arduino15\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4\arm-none-eabi\include\time.h:59:11: note: previous declaration 'time_t time(time_t*)'

 time_t    _EXFUN(time,     (time_t *_timer));

           ^

C:\Users\Andrea\Documents\Arduino\libraries\CircularBuffer\examples\CircularBuffer\CircularBuffer.ino: In function 'void setup()':

CircularBuffer:12:16: error: assignment of function 'time_t time(time_t*)'

  time = millis();

                ^

CircularBuffer:12:16: error: cannot convert 'long unsigned int' to 'time_t(time_t*) {aka long long int(long long int*)}' in assignment

C:\Users\Andrea\Documents\Arduino\libraries\CircularBuffer\examples\CircularBuffer\CircularBuffer.ino: In function 'void loop()':

CircularBuffer:18:2: error: 'buffer' was not declared in this scope

  buffer.push(reading);

  ^~~~~~

C:\Users\Andrea\Documents\Arduino\libraries\CircularBuffer\examples\CircularBuffer\CircularBuffer.ino:18:2: note: suggested alternative: 'buffer_t'

  buffer.push(reading);

  ^~~~~~

  buffer_t

CircularBuffer:20:15: error: invalid operands of types 'long unsigned int' and 'time_t(time_t*) {aka long long int(long long int*)}' to binary 'operator-'

  if (millis() - time >= 500) {

      ~~~~~~~~~^~~~~~

CircularBuffer:21:17: error: assignment of function 'time_t time(time_t*)'

   time = millis();

                 ^

CircularBuffer:21:17: error: cannot convert 'long unsigned int' to 'time_t(time_t*) {aka long long int(long long int*)}' in assignment

CircularBuffer:24:19: error: decltype evaluates to '<type error>', which is not a class or enumeration type

   using index_t = decltype(buffer)::index_t;

                   ^~~~~~~~

CircularBuffer:25:8: error: 'index_t' was not declared in this scope

   for (index_t i = 0; i < buffer.size(); i++) {

        ^~~~~~~

C:\Users\Andrea\Documents\Arduino\libraries\CircularBuffer\examples\CircularBuffer\CircularBuffer.ino:25:8: note: suggested alternative: 'index'

   for (index_t i = 0; i < buffer.size(); i++) {

        ^~~~~~~

        index

CircularBuffer:25:23: error: 'i' was not declared in this scope

   for (index_t i = 0; i < buffer.size(); i++) {

                       ^

exit status 1
'CircularBuffer' does not name a type; did you mean 'CellularBase'?

Any suggestions are welcome.
Thank you in advance.

Kind Regards

Shift and unshift method names are interchanged.

Hi,
shift and unshift method names are interchanged.
There in the doc is: "...shift() adds to the head...", but there in the code is defined as follows: "T shift();" and is commented as follows: "Removes an element from the beginning of the buffer.". Conversely the same applies for unshift method.

Namespace conflict with internal Arduino CircularBuffer

While trying to compile a Sketch downloaded from Barilla,
I found that I could not compile it since it required <RCircularBuffer.h> which was nowhere to be found.
The error of a missing index_t type prompted me to do some research and found your library.

To make it work I had to rename the Class and finally got the sketch to compile.

Is there any chance to implement a namespace?

The Sketch which breaks is the following
https://github.com/twofingerrightclick/BarillaPassiveCookingDevice/blob/main/Arduino/sketch_PastaThermometer_nano/sketch_PastaThermometer_nano.ino

The developer very likely did exactly what I did to make it work, rename Class and its occurrences in templates

Array-like indexed write operation?

CircularBuffer currently only supports array-like reading operation (data = buffer[0]), but not a writing one (buffer[0] = data). I know the library tries to protect internal buffers as much as possible, but this limitation is effectively making content of elements in CircularBuffers read-only. To modify a value in the buffer, one needs to reshift half of it (on average) or am I missing something?

severe calculating issue

Hi!
by testing with easy numbers, like 1000 for each etry of the buffer the calculation was wrong. I tryed to understand the following example:

CircularBuffer/examples/CircularBuffer/CircularBuffer.ino

please mention to change the line 26 from:

		avg += buffer[i] / buffer.size();

to:

		avg += buffer[i] / (float)buffer.size();

logfile and code with output:

11:01:27.395 ->
0 1000 0.00 24.00
1 1000 24.00 48.00
2 1000 48.00 72.00
3100072.0096.004100096.00120.0051000120.00144.0061000144.00168.0071000168.00192.0081000192.00216.0091000216.00240.00101000240.00264.00111000264.00288.00121000288.00312.00131000312.00336.00141000336.00360.00151000360.00384.00161000384.00408.00171000408.00432.00181000432.00456.00191000456.00480.00201000480.00504.00211000504.00528.00221000528.00552.00231000552.00576.00241000576.00600.00251000600.00624.00261000624.00648.00271000648.00672.00281000672.00696.00291000696.00720.00301000720.00744.00311000744.00768.00321000768.00792.00331000792.00816.00341000816.00840.00351000840.00864.00361000864.00888.00371000888.00912.00381000912.00936.00391000936.00960.00401000960.00984.00Average is 984.00

Average is 984.00

Avarage shall be 1000

after change of line 26:

11:25:56.682 ->

0 1000 0.00 24.39
1 1000 24.39 48.78
2 1000 48.78 73.17
3 1000 73.17 97.56
4100097.56121.9551000121.95146.3461000146.34170.7371000170.73195.1281000195.12219.5191000219.51243.90101000243.90268.29111000268.29292.68121000292.68317.07131000317.07341.46141000341.46365.85151000365.85390.24161000390.24414.63171000414.63439.02181000439.02463.41191000463.41487.80201000487.80512.20211000512.20536.59221000536.59560.98231000560.98585.37241000585.37609.76251000609.76634.15261000634.15658.54271000658.54682.93281000682.93707.32291000707.32731.71301000731.71756.10311000756.10780.49321000780.49804.88331000804.88829.27341000829.27853.66351000853.66878.05361000878.05902.44371000902.44926.83
38 1000 926.83 951.22
39 1000 951.22 975.61
40 1000 975.61 1000.00

Average is 1000.00

#include <CircularBuffer.h>

CircularBuffer<int, 41> buffer;

unsigned long timeI = 0;

#define SAMPLE_PIN 12

void setup() {
Serial.begin(115200);
pinMode(SAMPLE_PIN, INPUT);
timeI = millis();
}

void loop() {
// samples A0 and prints the average of the latest hundred samples to console every 500ms
//int reading = analogRead(SAMPLE_PIN);
int reading = 1000;
buffer.push(reading);

if (millis() - timeI >= 500) {
	timeI = millis();
	float avg = 0.00;
	// the following ensures using the right type for the index variable
	using index_t = decltype(buffer)::index_t;
	for (index_t i = 0; i < buffer.size(); i++) {
		Serial.print(i);
		Serial.print( buffer[i] );
  Serial.print(avg);
  avg += buffer[i] / (float)buffer.size();
  Serial.print(avg);
	}
	Serial.print("Average is ");
	Serial.println(avg);
}

}

//DO1TKN

Call to abort() is AVR-specific

Upgrading from an ATmega32u4 to ATSAMD21G board results in the following compiler error:

CircularBuffer.tpp:64:24: error: there are no arguments to 'abort' that depend on a template parameter, so a declaration of 'abort' must be available [-fpermissive]

  if (count <= 0) abort();

It seems like abort() is AVR-specific, and also probably bad practice to call directly. Recommend undoing the change in 86b33dc as an easy fix.

Allow using buffers as instance members

First of all, I would like to thank you for the nice work.

Right now it looks like it is impossible to use a circular buffer as an instance member since you are using the constexpr constructor. I am by no means a c++ expert but it does not look like there is any technical limitation that impedes doing it so maybe we could revert to using the normal constructor?

Minimal example:

#include <CircularBuffer.h>

class Foo {
    CircularBuffer<int, 400> buffer_;
};

void setup() {
  Foo foo1 = Foo();
  Foo foo2 = Foo();
}

void loop() {
}

Compiler error:

C:\Users\lnzmr\OneDrive\Documenti\Arduino\CircularBuffer_Test\CircularBuffer_Test.ino: In function 'void setup()':
CircularBuffer_Test:8:18: error: use of deleted function 'Foo::Foo(Foo&&)'
   Foo foo1 = Foo();
                  ^
C:\Users\lnzmr\OneDrive\Documenti\Arduino\CircularBuffer_Test\CircularBuffer_Test.ino:3:7: note: 'Foo::Foo(Foo&&)' is implicitly deleted because the default definition would be ill-formed:
 class Foo {
       ^~~
CircularBuffer_Test:3:7: error: use of deleted function 'CircularBuffer<T, S, IT>::CircularBuffer(CircularBuffer<T, S, IT>&&) [with T = int; unsigned int S = 400; IT = unsigned int]'
In file included from C:\Users\lnzmr\OneDrive\Documenti\Arduino\CircularBuffer_Test\CircularBuffer_Test.ino:1:0:
C:\Users\lnzmr\OneDrive\Documenti\Arduino\libraries\CircularBuffer/CircularBuffer.h:59:2: note: declared here
  CircularBuffer(CircularBuffer&&) = delete;
  ^~~~~~~~~~~~~~
CircularBuffer_Test:9:18: error: use of deleted function 'Foo::Foo(Foo&&)'
   Foo foo2 = Foo();
                  ^
Uso la libreria CircularBuffer alla versione 1.3.3 nella cartella: C:\Users\lnzmr\OneDrive\Documenti\Arduino\libraries\CircularBuffer 
exit status 1
use of deleted function 'Foo::Foo(Foo&&)'

Issue compiling on Arduino Nano 33 BLE

When I try to compile/upload the CircularBuffer example, I get the following error:

CircularBuffer:3:1: error: 'CircularBuffer' does not name a type; did you mean 'CellularBase'?

 CircularBuffer<int, 400> buffer;

 ^~~~~~~~~~~~~~

It seems to work when I switch the board to something else (e.g. UNO), but it does not work with the Nano 33 BLE.

Any help would be appreciated.

Board: Arduino Nano 33 BLE
Arduino IDE 1.8.11
CircularBuffer Library 1.3.3

Interrupt safe?

Is this implementation interrupt safe?

That is, if you add items in the interrupt handler and remove them in the main loop, will things work correctly?

Thanks!

Compilation error since v1.3.2

Hello,

I have been using CircularBuffer for several months in my sketch, but since version 1.3.2 I get a compilation error.
Version 1.3.1 works perfectly.

I use it for three very simple int array

CircularBuffer <int, 3> stackpage1;
CircularBuffer <int, 3> stackpage2;
CircularBuffer <int, 6> stackpage;

Here is the message of the compilation, in Arduino IDE:

`In file included from D:\Documents_D\Arduino\libraries\CircularBuffer/CircularBuffer.h:147:0,
from sketch\010_global_includes.h:43,
from D:\Documents_D\Arduino\ESP_GRAPHOCLOCK_V1-431\ESP_GRAPHOCLOCK_V1-431.ino:7:

D:\Documents_D\Arduino\libraries\CircularBuffer/CircularBuffer.tpp: In instantiation of 'T CircularBuffer<T, S, IT>::operator const [with T = int; unsigned int S = 3u; IT = unsigned char]':
sketch\024_Scroller_fnc.h:241:37: required from here

D:\Documents_D\Arduino\libraries\CircularBuffer/CircularBuffer.tpp:96:12: error: invalid use of member function (did you forget the '()' ?)
if (index >= size) return *tail;
^

D:\Documents_D\Arduino\libraries\CircularBuffer/CircularBuffer.tpp: In instantiation of 'T CircularBuffer<T, S, IT>::operator const [with T = int; unsigned int S = 6u; IT = unsigned char]':
sketch\024_Scroller_fnc.h:269:36: required from here

D:\Documents_D\Arduino\libraries\CircularBuffer/CircularBuffer.tpp:96:12: error: invalid use of member function (did you forget the '()' ?)`

Thanks for your help.

Writing a single data fills the buffer

v1.3.3
If a single data is written into the newly created buffer, buffer.size() reports one but all the other elements of the buffer is filled with the data.

#include <CircularBuffer.h>
CircularBuffer<long, 6> buffer;
uint16_t data1 = 1111;

void setup() 
{

  Serial.begin(9600);
  Serial.print("Buffer size before writing: ");
  Serial.println(buffer.size());
  buffer.push(data1);
  Serial.print("Buffer size after writing: ");
  Serial.println(buffer.size());
  Serial.print("Elements: ");
  Serial.print(buffer[0]);
  Serial.print(", ");
  Serial.print(buffer[1]);
  Serial.print(", ");
  Serial.print(buffer[2]);
  Serial.print(", ");
  Serial.print(buffer[3]);
  Serial.print(", ");
  Serial.print(buffer[4]);
  Serial.print(", ");
  Serial.println(buffer[5]);
   
}

void loop() {
  
}

Result:

09:28:44.723 -> Buffer size before writing: 0
09:28:44.856 -> Buffer size after writing: 1
09:28:44.889 -> Elements: 1111, 1111, 1111, 1111, 1111, 1111

The behavior can not be experienced in v1.3.0

Add 'copy to array' method

I'm using the cyclicbuffer to maintain a fixed size history/lookback of samples. Every so often I need to process the contents of the buffer. Using the buffer directly is too slow, so I first copy out the contents to an array via [] operator. A dedicated copy-to-array method would be more optimal as for starters, the if statement to check index bound could be skipped. I think it would just need a loop to copy everything from head to end of buffer, and another loop to copy from start of buffer to tail. This would also avoid the expensive of having to do % operation.

Supertype to allow pointers to CircularBuffers of different sizes

In my application, I'm using CircularBuffer to implement a queue the size of which is determined by a child class, which enqueues items to be consumed by a parent-class method. It would be useful if CircularBuffer<T,S> implemented a parent class ICircularBuffer, allowing my parent class to hold a pointer to that type, while the size was managed by my child class (which knows S at compile-time).

Is this a feature you'd consider adding?

How can I Declare CircularBuffer variable first and initialize later?

How can I Declare variable first and initialize later?
like this:
CircularBuffer cb_variable;

  cb_variable = CircularBuffer<int, 100>;

How can I Declare a CircularBuffer pointer and point to a CircularBuffer object?
CircularBuffer * cb_variable_ptr;

 cb_variable_ptr = &CircularBuffer<int, 100>;

Many thanks!

Remove item from the middle of the buffer

Hi,

I've just discovered this library yesterday and I am trying to use it my project. And I've read the other issues and what I am going to ask is something that was describe as absurd, as the title of this issues gives away: I need to remove an item that is not the head or tail.

The use case is very simple, someone can ask about something and it goes to the queue, but it can also cancel de order. So I need to remove that item from the queue before it gets processed. Does that make sense? Is there any workaround it today?

Thanks.

Code working on Arduino (Atmel AVR) not working on Teensy 3.2

Hello,

I have a bit of code that works just fine on an Arduino UNO, but when I try running the same code on the Teensy 3.2, it compiles, but I get erroneous data from the ring buffer. I am considering using STL::Vector but I thought I would ping you in case the issue report would help or if there was something obviously wrong in my code.

Thanks!

/*
 BrushlessPID - Input desired RPM serial plotter, PWM is calculated through PID
 
 Code Example for brushless gearmotors from Shenzhen Chihai Motor C O, Ltd.
 https://chihaimotor.en.alibaba.com/productgrouplist-810760854/brushless_DC_motor.html
 https://wiki.dfrobot.com/FIT0441_Brushless_DC_Motor_with_Encoder_12V_159RPM
 
 Uses interrupts to count pulses from the Frequency Generator (FG) signal
 from the motor.  Uses circular buffer to record nine timestamps from
 pulses to make an average from eight pulse width measurements.  Uses PID
 Library to reach desired RPM.
 
 Copyright (c) 2020 Corey McGuire.
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as 
 published by the Free Software Foundation, either version 3 of the 
 License, or (at your option) any later version.
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FIT NESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

// Using Circular Buffer library : https://github.com/rlogiacco/CircularBuffer
#define CIRCULAR_BUFFER_INT_SAFE
#include <CircularBuffer.h>

//Creating an array of length 9, one more than we will average since we must
//find the difference between 9 timestaps to get 8 values
CircularBuffer<unsigned long, 9> timings;

// Using Arduino-PID-Library : https://github.com/br3ttb/Arduino-PID-Library
#include <PID_v1.h>

double Setpoint ;                 // will be the desired RPM
double Input;                     // Frequency Generator (FG) signal from motor
double Output ;                   // Motor PWM signal to motor


// PID parameters : adjust these to get desired speed.
double Kp=.01, Ki=2, Kd=.01;


PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT); //create PID instance 
 
void setup()
{
  pinMode(11, OUTPUT); //PWM PIN 11 with PWM wire
  analogWrite(11, 0);
  Serial.begin(9600);   
    Setpoint = 75;                // Hardcode the target RPM
  
  myPID.SetMode(AUTOMATIC);       //Turn the PID on
  myPID.SetTunings(Kp, Ki, Kd);   //Adjust PID values

  //Attach interrupt handler to pin 2. Pins 2 and 3 have dedicated inturupts
  //More info, here : http://www.gammon.com.au/forum/?id=11488
  attachInterrupt (digitalPinToInterrupt (2), pulseRead, CHANGE);
}

//Function called on interrupt. Using a circular buffer in a FIFO fashion,
//we are storing timestamps to be calculated outside the function to keep
//the interrupt as short as possible.
void pulseRead() {
  timings.unshift(micros());
}

//Function for calculating average time between pulses. We disable inturrups
//for the brief time we are calculating the average because an inturrupt
//durring the calculation could cause a value to be recorded twice resulting
//in an errant "0" pulse length, ruining our average. There is little chance
//of this measure causing errent pulse length because the calculation should
//be so fast, that if the motor generates a pulse during this time, it will
//still be "HIGH" by the time the calculation exits and, thus, the interrupt
//is triggered.

float averagePulse(){
  long sum=0;
  noInterrupts ();
  for (int j=1 ; j < timings.size();j++){
    sum += timings[j-1]-timings[j];
  }
  interrupts ();
  return sum /(timings.size()-1.0);
}
 
void loop()
{
  // Read the value calculated from the average pulse width from Frequency
  // Generator (FG) to estimate RPM.
  Input = 111111/averagePulse();
  //PID calculation
  myPID.Compute();
  //Write the output (PWM) as calculated by the PID function
  analogWrite(11,Output); //LED is set to digital 3 this is a pwm pin. 
  //Send data by serial for plotting 
  Serial.print(Input);
  Serial.print(" ");
  Serial.println(Output);
  Serial.print(" ");  
  Serial.println(Setpoint);
  Serial.print(" ");
    if (Serial.available())  {
   Setpoint = Serial.parseInt();
    }
}

Output on Arduino
65.47 27.73 75.00 60.06 35.30 75.00

Output on Teensy
nan nan 75.00 nan nan 75.00

Question: How can store CircularBuffer in PSRAM on ESP32?

I would like to not use the RAM on ESP32, but rather use PSRAM attached using SPI interface. Data can be stored directly on PSRAM using ps_malloc() as per esp32-hal-psram.c.

I declare CircularBuffer<time_t, 2880> logTimeBuffer; globally that stores stuff in regular RAM. So is there a way to call ps_malloc() to use the PSRAM?

There is a good reference on doing this for ArduinoJson is here

CircularBuffer in RTC Memory while DeepSleep on ESP32

Hi,

I was trying to save my circular buffer in the RTC memory of my ESP32 while it is in DeepSleep. So I tried this simple function where I have struct and a circular buffer that are modified before going to Deep-sleep.
The struct is modified, the ID_msg is incremented every time but the buffer size is still 1 even is I push a new value at every wake up:

RTC_DATA_ATTR sensorsRecord newrecord{20, ID_sensor, ID_msg, epochUnion, ValueUnion, intValue, 30};
RTC_DATA_ATTR CircularBuffer<sensorsRecord, 50> test_SensorsDatas;

void test_RTC_memory2(){
    newrecord.ID_msg.value++;
    ID_msg.value++;
    Serial.println(String(newrecord.ID_msg.value));
    test_SensorsDatas.push(newrecord);
    Serial.println("buffer size: " + String(test_SensorsDatas.size()));
    esp_deep_sleep_start();
}

The circular buffer seem to be save in the RTC memory because if it's size is too large (>200) it can't compile because it's too big for the RTC memory.
So I don't know if it comes from my code or the library isn't compatible with RTC memory. Some advise or help would be appreciated. Thank you !

Overwriting pointers to objects and having memory leaks

The doc says:

The very same applies for the pop() and shift() operations as any dynamically allocated object is only detached from the buffer, but the memory it uses is not automagically released (see the Object.ino example)

Record* record = new Record(millis(), sample);  // a dynamically allocated object
buffer.push(record);

// somewhere else
if (!buffer.isEmpty()) {
    Record* current = buffer.pop();
    Serial.println(current.value());
    delete current; // if you don't do this the object memory is lost!!!
}

So it's clear that we need to manually clear memory for dynamically allocated objects. Now due to this being a circular buffer, a pointer to an object can be overwritten when we do

buffer.push(record);

in an already full buffer. In this case buffer.push() will return false, but the pointer and therefore the memory will be lost.
What we probably could do is returning the overwritten object instead of false, this way consumers will be able to do whatever they need with the object.

The other option, of course, is to check whether the buffer is full before doing push but that's not very convenient in my opinion.

Or am I missing something and there are better approaches for this?
Thanks.

count should not go below 0

I would add a check for shift & pop that before doing anything check if the fifo is non empty. Otherwise counts gets negative and the pointers get unaligned.

Something like:
if (!count) return *head;
before line 69 and 79.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.