interupting task or multi tasking

So here is the thing. I have been learning everything I can on the web but I need to ask some questions to see if what my next step can be done in Arduino.

So I have some code that does a neopixel LED animation however it last almost ten seconds. and once its running I can send commands to Arduino. How could I change this? How can I interrupt my animation and send a new command to begin a new animation when I send a new value over the LBM313? is this possible? I have been looking at FreeRTOS but not sure if this is what I should do or maybe a serial interrupt to send the new command. If I choose serial interrupt, how would I even go about it. maybe something as simple as if I receive a serial interrupt then restart the "void loop()" and look for the value I sent. not sure.

I am using the LighBlue Bean with BLE technology which connect the BLE LBM313 to the Bean Arduino board through serial connect.

The animation code, it has delays in it?

Did I post in one of your threads an example of function with built in timer and state machine? Perhaps it was someone else.

Yes you can. The code can be small for most tasks. The idea may require a different more flexible view. And you don't need an OS with overhead in cpu cycles, interrupt, RAM and flash to do the same, only slower.

it last almost ten seconds. and once its running I can send commands to Arduino. How could I change this?

By writing your code as a state machine. See my http://www.thebox.myzen.co.uk/Tutorial/State_Machine.html Or Robin2's several things at once http://forum.arduino.cc/index.php?topic=223286.0

How can I interrupt my animation and send a new command to begin a new animation when I send a new value over the LBM313? is this possible?

No.

have been looking at FreeRTOS but not sure if this is what I should do

It is not.

So you ignored everything in this thread then

Well look at this one

I no longer need to wonder if I need to help the OP learn. OP is window shopping.

ok, Grumpy and goforsmoke. I am not sure about yall but I have surpassed my previous post by a long shot. my last post was me learning what I now think are some of the more basic things. As far as the comment of window shopping well i would disagree as my newest sketch is mine. I am using some things from the neopixel library but kinda need to… So with all that said you both are more then welcome to help but if you have negative comments then please leave them behind and go troll another post.

GoForSmoke:
I no longer need to wonder if I need to help the OP learn. OP is window shopping.

As far as if im using delay, no I am not. This is what the animation looks like.

void theaterChaseRainbow(uint8_t wait) {
  for (int j = 0; j < 256; j++) {   // cycle all 256 colors in the wheel
    for (int q = 0; q < 3; q++) {
      for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, Wheel( (i + j) % 255)); //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, 0);      //turn every third pixel off
      }
    }
  }
}

Now this gets called on when I send a command via serial from my BLE connection as I use the Lighblue Bean which is connected to a BLE chip over serial.

I have looked around at possible ways that I could interrupt this and there is one that scrams to me the most. In one of the codes that Adafruit uses for a wearable project they somehow use come code to take whatever animation they input to then break it into a 30FPS animation allowing for the time in between to be polled. Kinda smart actually never would have thought of this. But then again i am new. So I am currently dissecting this and seeing how it works to then write something similar for my sketch. If you would like or dont mind disecting or explaining there example then much would be appreciated. but I have litterally spent the last 5 days learning arduino as much as possible. As I am a disabled military veteran going to college with no job cause the government is paying for me to study so I sleep 4 hours like I always have and use the rest of my time to learn and now im hungry for arduino, so your choice to help me or not.

As far as if im using delay, no I am not

void theaterChaseRainbow(uint8_t wait) {
  for (int j = 0; j < 256; j++) {   // cycle all 256 colors in the wheel
    for (int q = 0; q < 3; q++) {
      for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, Wheel( (i + j) % 255)); //turn every third pixel on
      }
      strip.show();

      delay(wait);

Okay. So that establishes your definition of “not doing something”

well, sorry grabbed from the wrong sketch but the Delay(wait) is not in the sketch i am using.

how ever void the wait in this section is still in my sketch theaterChaseRainbow(uint8_t wait) but as I stated before the animation gets broken into 30FPS via this

 t = micros();                            // Current time
    if((t - prevTime) >= (1000000L / FPS)) { // 1/30 sec elapsed?
      prevTime = t;
      break;

OK, so we’ve established (I think) that you’re not using delay() or delayMicroseconds() or any other variant of a busy-wait, and that your update rate is only 30Hz, I’m not sure why you’re asking about interrupts and operating systems.

(It may surprise you, but we can’t see your code, so any talk of dissection is moot)

I was talking about interupts at first but as I have come to understand there is really no software interrupts and FreeRTOS library isnt going to be what I want then I have looked for other things that might work. That’s when I came across this sketch and I am not trying to fully understand it.

how does it know to split the function into 30FPS I get it but I dont. cant really explain were my thought is on it. but if anyone wants to explain the code in depth when it concerns splitting the animation/task into 30FPS then please by all means I would appreciate it.

// Bluetooth Goggles Sketch -- shows the Adafruit Bluefruit LE UART Friend
// can be used even with Trinket or Gemma!

// https://www.adafruit.com/products/2479

// Works in conjunction with Bluefruit LE Connect app on iOS or Android --
// pick colors or use '1' and '2' buttons to select pinwheel or sparkle modes.
// You can try adding more, but space is VERY tight...helps to use Arduino IDE
// 1.6.4 or later; produces slightly smaller code than the 1.0.X releases.

// BLUEFRUIT LE UART FRIEND MUST BE SWITCHED TO 'UART' MODE

#include <SoftwareSerial.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR_ATtiny85__ // Trinket, Gemma, etc.
 #include <avr/power.h>
#endif

#define RX_PIN    2 // Connect this Trinket pin to BLE 'TXO' pin
#define CTS_PIN   1 // Connect this Trinket pin to BLE 'CTS' pin
#define LED_PIN   0 // Connect NeoPixels to this Trinket pin
#define NUM_LEDS 32 // Two 16-LED NeoPixel rings
#define FPS      30 // Animation frames/second (ish)

SoftwareSerial    ser(RX_PIN, -1);
Adafruit_NeoPixel pixels(NUM_LEDS, LED_PIN);

void setup() {
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000L)
  // MUST do this on 16 MHz Trinket for serial & NeoPixels!
  clock_prescale_set(clock_div_1);
#endif
  // Stop incoming data & init software serial
  pinMode(CTS_PIN, OUTPUT); digitalWrite(CTS_PIN, HIGH);
  ser.begin(9600);

  pixels.begin(); // NeoPixel init
  // Flash space is tight on Trinket/Gemma, so setBrightness() is avoided --
  // it adds ~200 bytes.  Instead the color picker input is 'manually' scaled.
}

uint8_t  buf[3],              // Enough for RGB parse; expand if using sensors
         animMode = 0,        // Current animation mode
         animPos  = 0;        // Current animation position
uint32_t color    = 0x400000, // Current animation color (red by default)
         prevTime = 0L;       // For animation timing

void loop(void) {
  int      c;
  uint32_t t;

  // Animation happens at about 30 frames/sec.  Rendering frames takes less
  // than that, so the idle time is used to monitor incoming serial data.
  digitalWrite(CTS_PIN, LOW); // Signal to BLE, OK to send data!
  for(;;) {
    t = micros();                            // Current time
    if((t - prevTime) >= (1000000L / FPS)) { // 1/30 sec elapsed?
      prevTime = t;
      break;                                 // Yes, go update LEDs
    }                                        // otherwise...
    if((c = ser.read()) == '!') {            // Received UART app input?
      while((c = ser.read()) < 0);           // Yes, wait for command byte
      switch(c) {
       case 'B':       // Button (Control Pad)
        if(readAndCheckCRC(255-'!'-'B', buf, 2) & (buf[1] == '1')) {
          buttonPress(buf[0]); // Handle button-press message
        }
        break;
       case 'C':       // Color Picker
        if(readAndCheckCRC(255-'!'-'C', buf, 3)) {
          // As mentioned earlier, setBrightness() was avoided to save space.
          // Instead, results from the color picker (in buf[]) are divided
          // by 4; essentially equivalent to setBrightness(64).  This is to
          // improve battery run time (NeoPixels are still plenty bright).
          color = pixels.Color(buf[0]/4, buf[1]/4, buf[2]/4);
        }
        break;
       case 'Q':       // Quaternion
        skipBytes(17); // 4 floats + CRC (see note below re: parsing)
        break;
       case 'A':       // Accelerometer
#if 0
        // The phone sensors are NOT used by this sketch, but this shows how
        // they might be read.  First, buf[] must be delared large enough for
        // the expected data packet (minus header & CRC) -- that's 16 bytes
        // for quaternions (above), or 12 bytes for most of the others.
        // Second, the first arg to readAndCheckCRC() must be modified to
        // match the data type (e.g. 'A' here for accelerometer).  Finally,
        // values can be directly type-converted to float by using a suitable
        // offset into buf[] (e.g. 0, 4, 8, 12) ... it's not used in this
        // example because floating-point math uses lots of RAM and code
        // space, not suitable for the space-constrained Trinket/Gemma, but
        // maybe you're using a Pro Trinket, Teensy, etc.
        if(readAndCheckCRC(255-'!'-'A', buf, 12)) {
          float x = *(float *)(&buf[0]),
                y = *(float *)(&buf[4]),
                z = *(float *)(&buf[8]);
        }
        // In all likelihood, updates from the buttons and color picker
        // alone are infrequent enough that you could do without any mention
        // of the CTS pin in this code.  It's the extra sensors that really
        // start the firehose of data.
        break;
#endif
       case 'G':       // Gyroscope
       case 'M':       // Magnetometer
       case 'L':       // Location
        skipBytes(13); // 3 floats + CRC
      }
    }
  }
  digitalWrite(CTS_PIN, HIGH); // BLE STOP!

  // Show pixels calculated on *prior* pass; this ensures more uniform timing
  pixels.show();

  // Then calculate pixels for *next* frame...
  switch(animMode) {
   case 0: // Pinwheel mode
    for(uint8_t i=0; i<NUM_LEDS/2; i++) {
      uint32_t c = 0;
      if(((animPos + i) & 7) < 2) c = color; // 4 pixels on...
      pixels.setPixelColor(   i, c);         // First eye
      pixels.setPixelColor(NUM_LEDS-1-i, c); // Second eye (flipped)
    }
    animPos++;
    break;
   case 1: // Sparkle mode
    pixels.setPixelColor(animPos, 0);     // Erase old dot
    animPos = random(NUM_LEDS);           // Pick a new one
    pixels.setPixelColor(animPos, color); // and light it
    break;
  }
}

boolean readAndCheckCRC(uint8_t sum, uint8_t *buf, uint8_t n) {
  for(int c;;) {
    while((c = ser.read()) < 0); // Wait for next byte
    if(!n--) return (c == sum);  // If CRC byte, we're done
    *buf++ = c;                  // Else store in buffer
    sum   -= c;                  // and accumulate sum
  }
}

void skipBytes(uint8_t n) {
  while(n--) {
    while(ser.read() < 0);
  }
}

void buttonPress(char c) {
  pixels.clear(); // Clear pixel data when switching modes (else residue)
  switch(c) {
   case '1':
    animMode = 0; // Switch to pinwheel mode
    break;
   case '2':
    animMode = 1; // Switch to sparkle mode
    break;
   case '3':
    break;
   case '4':
    break;
   case '5': // Up
    break;
   case '6': // Down
    break;
   case '7': // Left
    break;
   case '8': // Right
    break;
  }
}

@itkujo, if you keep jumping from one piece of code to another you are not going to solve your problem and you are not going to learn anything.

In the earlier code (Reply #4) you have a nest of three FOR loops. It will be impossible to make a responsive program with that sort of thing because each FOR loop will run to completion.

For a responsive program you need to get rid of ALL those FOR loops and allow loop() to manage the iteration using variables to count things. That way only one piece of the animation happens on each occasion and you can interrupt it easily.

The program in Reply #8 has some of the same problems with a completely unnecessary for(;:wink: { and while((c = ser.read()) < 0); // Wait for next byte in different places.

Have a look at Planning and Implementing a Program and Serial Input Basics

…R

Your animation routine as posted does not exit until the animation has completed.

What it should do is run a short piece then return, keeping track of what it did as process state so that when called next time it runs the next short piece which may be the same piece of code until what it is doing is done or some other piece, the control of which is by changing the state value.

With this technique, a routine that needs to wait will check the time and if it is not up yet then it returns to let the other routines run instead of blocking them from executing. . If nothing in your whole sketch runs more than a short piece at a time, ALL tasks can get a chance to run their next short piece at rates over 50000 times per second. You can add a routine that counts loop()s and prints the count every second, I typically get 57KHz to 67KHz in small demos that only do a few things and got 87KHz on a special blink random leds running soft-PWM written for one project.

Think of loop() as a wheel and your project as a road. What most people learn starting out is to make a wheel that in one turn reaches the end of the road, everything done in one pass. Then when the road is extended they keep the "big wheel" concept and if anything make it bigger and more complicated.

Nix that. Learn to break the project down. Instead of loops inside of routines, keep track of indexes and do one step per pass of the routine per one pass through loop() itself, letting your other routines have a chance to get their steps in including the ones that read serial input and sensors.

There are permanent threads on this forum and web tutorials to teach the ways to make it work, how to make things happen on time and/or other events, how to use finite state machines, it is all available but warning: you won't really understand just by reading about it, you HAVE to use these techniques and go through mistakes to get much good out of it which won't happen in a day or two.

Your choice. Do enough work to at least be able to ask more specific questions and act on the answers you get until you can ask better questions. You can progress and get help that way. Ask the same things in different ways and what does that say?

Thank you both, i really appreciate both responses. I will look into the tutorials that you both have suggested.

Goforsmoke thanks for explaining the whole wheel thing really help me understood the different thought process here. I guess all I kept thinking was that everything needed be that big wheel in arduino. I will continue to read and practice. currently all I have is two motors and 12 neopixel LEDs in a ring. I wanted to see how much arduino I could learn if I am constantly around it for the next 2 months at about 30+ hours a week. I kind of have made arduino my job till january. I will continue to learn after this but once my new set of classes start in january time will be alot more constricted. So any tutorial that you really think I should dive into please let me know.

I am a systems administrator so I have always been the electrical and programming engineers enemy. as I use the products created. But I figured id start learning some basic on arduino and maybe later even learn some C++. I really like the arduino for its simplicity that I have come to see so far and I would like to introduce it to young people like my sibling that have always wanted to understand computers and microcontrolers a little more. But to do that I need to build my knowledge.

Robin, Thanks alot for the links I really have been enjoying the serial input basics one.

Hopefully with continued guidace from people like you guys I can come to understand this in the coming months alot more.

The approach is to make short event triggered routines that work together inside of loop().

Events may be a timeout or a pin state change or a flag set by an interrupt or the value of a variable.

I use state machines to process text 1 char at a time, have for a long time (80's) but that's not simple.

I posted you an example of a timer and state machine combined in one function as a way to get rid of delays in another thread. It's not perfect, there's no off switch but that can be achieved easily enough.

If you want good tutorials then there are 3 addresses in my signature space just below. The first addresses blocking code and timers to show how to make multiple things happen together. The second is different ways to read serial data without blocking, one method is by using a basic state machine. The third is about interrupts. Just the 1st 2 of those 3 can get you started on automation, there are times when interrupts are called for.

they somehow use come code to take whatever animation they input to then break it into a 30FPS animation allowing for the time in between to be polled. Kinda smart actually never would have thought of this.

Good because it is a pretty stupid way of doing something that is simply solved with a state machine.

Grumpy_Mike: Good because it is a pretty stupid way of doing something that is simply solved with a state machine.

Somehow...... they... might use a state machine. The description is far too loose to say they don't.

Robin2 or GoForSmake or anyone else for that matter. I have started writing my own code from scratch. doing it all in small sections as I learn. I have been doing some good progress but I know that this project as well as any other in the future are going to require me to have an understanding of serial input into my Arduino board.

Read the beginners link that robin gave me but now I’m trying to understand some things that others have done to get the IOS app to talk via serial to use things like the buttons and sliders for my sketches. What I have seen done so far is something of this sort in my defining section.

#define BUF_SIZE 64
char buffer[BUF_SIZE] = {0};

// Sandbox control IDs
const char MSG_XYPAD_X = 8;
const char MSG_XYPAD_Y = 9;
const char MSG_XYPAD_Z = 11;
const char MSG_PAGEA_SLIDER_0 = 0;
const char MSG_PAGEA_SLIDER_1 = 2;


char brightness = 30;

This person also uses this bit

 for (uint16_t i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, strip.Color(red, green, blue));
  }
  strip.show();

and this bit

      // Iterate over sandbox messages by processing groups of two bytes.
      for (char i = 0; i < length - 1; i += 2) {

        if (buffer[i] == '1') {
          red = 40;
          blue = 255;
          green = 10;
          renderBasic();


        } else if (buffer[i] == 'y') {
            red = 255;
          blue = 0;
          green = 255;
          renderBasic();
        }else if (buffer[i] == MSG_XYPAD_X) {
            red = buffer[i + 1];
            renderBasic();


          }
          else if (buffer[i] == MSG_XYPAD_Y) {
            blue = buffer[i + 1];
            renderBasic();


          }
          else if (buffer[i] == MSG_XYPAD_Z) {
            green = buffer[i + 1];
            renderBasic();

So my question is how does the uint16_t work and the buffer work in these bits. If there is a good tutorial on uint#_t’s with serial please let me know. I am using the light blue bean from the apple IOS app store and when I press any button it alwasy says it sent a value between 0x000000 to 0xFFFFFF if im not mistaken. I can conrfirm when my girlfriend arrives home as she has my phone. I hope my questions are getting better. I really appreciate all the help.

Also just to make sure I’m doing the right thing. Should I have written a new thread for this question? I just want to make sure I am following the guide lines and rules.

What is this animation supposed to do? Besides a whole "frame" at a time?

Not HOW but WHAT.

uint16_t means unsigned 16 bit integer type. All variables have a type, it tells the compiler what you want to use. If you include arduino.h, you can call the type ‘word’ or ‘unsigned int’.

uint16_t can be 0 to 65535

int (also called int16_t) is the signed 16 bit integer type. They can be -32768 to 32767.

itkujo: I have started writing my own code from scratch. doing it all in small sections as I learn.

You have not posted a complete compilable program. At all stages in development you should compile and test your program regularly. Don't move on to a new piece until the existing stuff works properly.

I have been doing some good progress but I know that this project as well as any other in the future are going to require me to have an understanding of serial input into my Arduino board.

Unless you have some unusual requirements most of what a beginner needs to know is in Serial Input Basics - simple reliable ways to receive data. There is also a parse example.

...R

Nick's State Machine example in http://gammon.com.au/serial should be enough to read letter-number commands on the fly as opposed to collect-then-parse.

I would like to get the OP started on breaking the sketch up into tasks rather than big-wheel code.

Something like:

const byte PIXELS = 32; byte pixelNumber = 0; byte userCommand = 0;

void loop() { // output task pixelNumber = setTheNextPixel( pixelNumber ); // sets pixels then waits 32 millis

// input task if ( Serial.available()) { userCommand = getInput(); }

// process task switch ( userCommand ) { // not sure what this should do yet..... but it generates data to drive the pixels } }

Where each task runs independently and coordinates only through values of variables. Any new effects or inputs should be made by adding task(s) that modify the values. Consider that the order of tasks in loop() here does not matter much at all.

When inputs don't have to wait for arrays to be processed then input can come at any time.

You have 16000 cpu cycles per millisecond. Don't waste them and your code will fly on little wheels.