0

I'm having a double buffer to write data from sensors to SD card. inBuf points to the buffer that are written into (from sensors). The other buffer write data to SD card.

char buffer[2][BUFLEN];
volatile int inBuf = 0;

inBuf = 1 - inBuf;

However, the update of inBuf does not work. Firstly inBuf is 0, and after that inBuf becomes 32!!! I tried different data types: boolean, uint8_t, int and the results are the same.

How could I fix this problem? Also, what datatype should I use for inBuf, as it's really just one bit?

I ended up using the following:

inBuf = inBuf? 0:1; 

but seems really complicated and unnecessary.

EDITS: Sorry for was not being clear previously. It turns out that I had an overflow in the code:

char buffer[2][BUFLEN];
volatile uint16_t bufferCounter;
volatile int inBuf = 0;
volatile bool outBufHasData = false;

Inside the interrupt handler:

if (bufferCounter < BUFLEN - SAMPLESIZEINCHAR + 1) {
  epoch = now();
  proximity = vcnl.readProximity();
  ambientLight = vcnl.readAmbient();

  // format to be fixed length as opposed to variable length
  // sacrifice overhead in written data with simpler and more robust code
  // since we know exactly how much to increment after each write
  int written = snprintf(&buffer[inBuf][bufferCounter], SAMPLESIZEINCHAR,
        "%10lu,%5d,%5d\n",
        epoch, proximity, ambientLight);

  if (written > 0) {
    bufferCounter += written;
  }
} else {
  // only switch buffer if out buffer is written to SD card
  if (!outBufHasData) {
    inBuf = inBuf? 0:1;    
    bufferCounter = 0;
    outBufHasData = true;
  }
}

Then in the for loop, where the buffer is written to SD card when the buffer is full:

  if (outBufHasData) {
    myFile.print(buffer[1 - inBuf]);
    myFile.close();
    outBufHasData = false;
  }

Previously, I had bufferCounter < BUFLEN !! Thus I was writing over the memory of the buffer, and spill into bufferCounter and inBuf. That's why I got the value 32 of inBuf, which is the ASCII code of space. Mystery resolved!!

5
  • 3
    I see you have inbuf volatile. Is there an interrupt involved somewhere? Care to share your actual code instead of just 2 lines?
    – Majenko
    Jun 1 '17 at 8:03
  • 3
    You obviously have a bug somewhere, but since it is not in the snippet you posted, we cannot help you. Could you post a Minimal, Complete, and Verifiable example showing the problem? Jun 1 '17 at 8:39
  • 4
    My guess is that, since inBuf immediately follows buffer in the definitions you are overflowing buffer and clobbering the contents of inBuf - but that's just a guess since we cannot see your code!
    – Majenko
    Jun 1 '17 at 11:07
  • @Majenko That's a correct guess! My code has overflow and rewrote the number 1 to by space char, which is 32. If you want you could add an answer and I'll accept that!! Jun 4 '17 at 6:52
  • At least part of your edit, whilst clarifying what you are asking, also appears to contain an answer. It would be better to edit your question to clarify the original problem, and then post the solution and explanation as an answer, and then accept your own answer. I will vote to reopen the question, so that you can post your own answer. Your question (and answer) may prove to be useful for someone else. Jun 4 '17 at 7:50
2

Seeing as your data typpe has the volatile keyword maybe the value of inBuf is being changed on another section of code like an interupt, other wise i see no reason for the variable to have a value of 32.

If you want to only use one bit you should just use the boolean data type with a true or false value.

In that bit of code i assume you are trying to invert the value of the bit, with the boolean you could always use the NOT operator:

inBuf != inBuf;
1

If you want a variable to be 'yes' and 'no' or perhaps '0' and '1', then you can use a boolean which is 'true' or 'false'. With a boolean you can use logic operators:

boolean dataReady = false;
dataReady = !dataReady;
if( dataReady) ...

A boolean on a 8-bit AVR chip (Arduino Uno,Leonardo,Nano,Mega) is 8 bit. You could also use a byte and make it 0 or 1.

A 8-bit variable is often used when a interrupt routine sets a flag. By making that flag only 8 bit and volatile, it can be used in the loop function as well without the need to disable the interrupts. Reading and writing a 8 bit variable can not be interrupted by an interrupt routine.

Using 8 bits when only 1 bit is needed is normal. You don't have to worry about that.

When you need hundreds of 1 bit variables, then it is possible to select each bit with macro's or a lot #define to select each bit. This is almost never used in normal code, but almost always used for the registers of a sensor.
And last but not least: a struct with bit fields packs the bits. That can be handy sometimes.

3
  • this answer does not answer the OPs question. Jun 1 '17 at 15:18
  • I was trying to see through the little information and tried answer the question that the OP probably should have been asking.
    – Jot
    Jun 2 '17 at 13:31
  • Thank you though, I'll be clear next time asking question! Jun 4 '17 at 6:53

Not the answer you're looking for? Browse other questions tagged or ask your own question.