Coder Social home page Coder Social logo

wizard97 / arduinoringbuffer Goto Github PK

View Code? Open in Web Editor NEW
108.0 10.0 23.0 39 KB

A Simple Interrupt Safe Ring (Circular) Buffer Queuing Library for Programming with Arduino's and other Embedded platforms

License: MIT License

C 50.55% C++ 49.45%

arduinoringbuffer's Introduction

ArduinoRingBuffer

This is a simple ring (FIFO) buffer library for the Arduino. It is written in vanilla C, and can easily be modified to work with other platforms. It can buffer any fixed size object (ints, floats, structs, etc...).

Project History

I needed a way to buffer sensor events for a group engineering IOT project that I was working on at Cornell. We needed to record changes in IR trip wires that happened in ms timeframes, and tight loop polling was not working. We needed interrupts and a buffering library. I couldn't find any suitable Arduino Libraries that could buffer any sized object, so I wrote my own.

I decided to give object oriented programming a shot using only C (no C++) with this library, of course, it still compiles with C++ compilers such as in the Arduino IDE. Using C structs and function pointers, the library creates RingBuf objects that are complete with their own methods and attributes. Note that every method (except constructor), takes a RingBuf *self pointer. This is the equivalent of the this pointer in C++, but the C++ compiler automatically passes it behind the scenes. For this library, you must manually pass a the RingBuf *self pointer as the first argument, like this:

int foo = 1234;
RingBuf *buf = RingBuf_new(sizeof(int), 20);
buf->add(buf, &foo);

What about C++ templates?

I recently created a C++ alternative to this library that utilizes the power of C++ templates, now you can perform deep copies of objects. Check it out: C++ alternative library.

Use Cases

A ring buffer is used when passing asynchronous io between two threads. In the case of the Arduino, it is very useful for buffering data in an interrupt routine that is later processed in your void loop().

Supported Platforms

The library currently supports:

  • AVR
  • ESP8266

Install

This library is now availible in the Arduino Library Manager, directly in the IDE. Go to Sketch > Include Library > Manage Libraries and search for RingBuf.

To manually install this library, download this file as a zip, and extract the resulting folder into your Arduino Libraries folder. [Installing an Arduino Library] (https://www.arduino.cc/en/Guide/Libraries).

Examples

Look at the examples folder for several examples.

Contributing

If you find this Arduino library helpful, click the Star button, and you will make my day.

Feel free to improve this library. Fork it, make your changes, then submit a pull request!

API

Constructor

RingBuf *RingBuf_new(int size, int len);

Creates a new RingBuf object of len elements that are size bytes each. A pointer to the new RingBuf object is returned on success. On failure (lack of memory), a null pointer is returned. This would be the equivalent of new RingBuf(int size, int len) in C++.

Deconstructor

int RingBuf_delete(RingBuf *self);

Deletes the RingBuf, and frees up all the memory associated with it.

Methods

add()

int add(RingBuf *self, void *object);

Append an element to the buffer, where object is a pointer to object you wish to append. Returns -1 on a full buffer. On success, returns the position (index) in the buffer where the element was added.

peek()

void *peek(RingBuf *self, unsigned int num);

Peek at the num'th element in the buffer. Returns a void pointer to the location of the num'th element. If num is out of bounds or the num'th element is empty, a NULL pointer is returned. Cast the result of this call into a pointer of whatever type you are storing in the buffer. Note that this gives you direct memory access to the location of the num'th element in the buffer, allowing you to directly edit elements in the buffer. Note that while all of RingBuf's public methods are thread safe (including this one), directly using the pointer returned from this method is not thread safe. If there is a possibility an interrupt could fire and remove/modify the item pointed to by the returned pointer, disable interrupts first with noInterrupts(), do whatever you need to do with the pointer, then you can reenable interrupts by calling interrupts().

pull()

void *pull(RingBuf *self, void *object);

Pull the first element out of the buffer. The first element is copied into the location pointed to by object. Returns a NULL pointer if the buffer is empty, otherwise returns object.

numElements()

unsigned int numElements(RingBuf *self);

Returns number of elements in buffer.

isFull()

bool isFull(RingBuf *self);

Returns true if buffer is full, otherwise false.

isEmpty()

bool isEmpty(RingBuf *self);

Returns true if buffer is empty, false otherwise.

License

This library is open-source, and licensed under the MIT license. Do whatever you like with it, but contributions are appreciated.

arduinoringbuffer's People

Contributors

maxgerhardt avatar per1234 avatar scls19fr avatar wizard97 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

arduinoringbuffer's Issues

add() (or new push()) that overwrites oldest?

I'm curious if there is a way to add an option to add(), or a new call (push()?) that would always add to the queue by "pushing" the oldest item out of the queue?

In the current implementation it appears that if we are adding and the buffer fills, we are forced to lose the "new" items. This works in two of our cases, but we have one where we want the "oldest" data to be lost so that the queue contains the latest {x} records.

Does this make sense? Thoughts?

Compatibility with ESP8266?

Hi there,

I was hoping to use your library on the ESP8266, but I get the following error:

...snip...
WARNING: library RingBuf claims to run on [avr] architecture(s) and may be incompatible with your current board which runs on [esp8266] architecture(s).
C:\Users\blark\Documents\Arduino\libraries\RingBuf\RingBuf.c:9:25: fatal error: util/atomic.h: No such file or directory

 #include <util/atomic.h>
...snip...

I took a look and it seems that atomic operations are possible on the ESP8266 (http://www.esp8266.com/viewtopic.php?f=9&t=618) however atomic.h is not implemented. Probably some wifi-related reason. Is there any hope of getting the code working on this platform?

Test Cases - Help Wanted!

Test cases are needed to validate changes to the library. Really want to merge the dev branch into master, but need to ensure there are no bugs.

Any commits that address this will be really appreciated! :)

Issues compiling for ESP8266 with Arduino IDE

I've been playing with the RingBuf library and had it working nicely on an Uno. I then compiled it for the ESP8266 and got this error: 'invalid conversion from 'void*' to 'int*' [-fpermissive]'

I think these would be the pertinent lines...
RingBuf *sensor1 = RingBuf_new(sizeof(unsigned int), HISTORICAL_ARRAY_SIZE);
int *data_ptr;
data_ptr = sensor1->peek(sensor1, i); ////// this is where it errors out

I've tried versions 1,2 and 3 all with the same results

peek() at head or tail?

Thank you for the great work! I'm just starting to do some development using this library, and so far so good ... except ... :-)

I'm wanting to use peek() to look at the next element to be pulled from the queue ... but it requires a num ... and I don't know what that num is? I can fetch the numelements() but that doesn't give it to me either.

Is there a way to find out what the "first" or "head" num is? And in that case the "last" or "tail" might be useful also?

ESP32 support

Hi,
this is exactly what I would need in an ESP32 project, but the library is only targeted for AVR and ESP8266. I played a bit with the header file, but it is not a trivial change (for me). Any chance for ESP32 support ?

Atomicity locking.

For AVR 8 bit you need to introduce some atomicity locking of the ring buffer. Otherwise subtle runtime nightmares...

Take a look at Dean Camera's solution in LUFA "ringBuffer.h"using the AVR libc tools in <util/atomic.h> as the right way to provide atomic protection.

Cheers, Phillip

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.