Gemma Hoop help

Wearable electronics: boards, conductive materials, and projects from Adafruit!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
Johno2000
 
Posts: 11
Joined: Tue Jun 03, 2014 9:58 pm

Gemma Hoop help

Post by Johno2000 »

I am making some goggles using a gemma and the hoop project. the code I am trying to use is this https://github.com/HerrRausB/GemmaHoopAnimator

What I am trying to do is mirror the pixel animation on the two 16 neopixel rings I have, so they are a reflection of each other instead of them just copying each other like they are now.

I think I need to add some code that reads each pixel then writes its reflection to the other ring and increase the 16 pixel "NUM_PIXEL" to 32, and I think i need to connect the rings together by the data out and data in pads on the 16 neopixel ring boards

Am I right and how do I do this... I really want to understand how the mirror code works so i can eventually add it to other things

Thank you anyone reading this

User avatar
SeiRruf
 
Posts: 82
Joined: Thu Sep 04, 2014 3:07 am

Re: Gemma Hoop help

Post by SeiRruf »

You'll be happy to know mirroring is relatively simple :)

You want your second ring to display in inverse of the first ring, correct?

To do that, wire the Data IN of your second ring to the Data OUT of your first. You may also daisy chain the rings VCC and GND with the previous one as well. When you're done, you should have only 3 wires to control both rings. VCC, GND, and one Data IN (which connects to pin 0 on your GEMMA).

Then in the GemmaHoopAnimator.ino file, replace the code within, with this code provided. You won't need to change the other two library files:

Code: Select all

/******************************************************************************
 *
 * this file is part of the gemma hoop animator example sketch
 *
 * it 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.
 *
 * it 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 Lesser General Public License for more details.
 *
 * you should have received a copy of the GNU Lesser General Public
 * License along with NeoPixel.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * ----------------------------------------------------------------------------
 *
 * this is the general implementation of the gemma hoop animator - unless you 
 * don't like the preset animations or find a major bug, you don't need to 
 * change anything here
 *
 * ----------------------------------------------------------------------------
 *
 * this sketch simply cycles through the action list defined in
 * GemmaHoopActiuonList.h. it should run on any arduino compatible µC
 * and with all available NeoPixel products - you just have to adjust
 * the general settings in GemmaHoopActionList.h.
 *
 * it hereby loads the individually defined actions one after the other
 * and continously steps through these actions according to the action
 * speed specified for the respective action.
 *
 * independently from stepping through the current action, it also changes 
 * the current color according to the color change interval and the 
 * respective color selection method (random or spectrum)
 * definied for the current action. 
 *
 * each action will continue according to the current action duration 
 * as defined in the action list. then the next action will be loaded. when
 * the last action in the list is reached, it will continue with the first 
 * action.
 *
 * ----------------------------------------------------------------------------
 *
 * the number of actions possible is limited by the RAM of the used µC. shall
 * the list be too long, the µC will crash and nothing will go on.
 *
 * i'd rather like to put the action definitions on a SD card or any external
 * storage to get more space for as well more different action implementations
 * as an unlimited number of actions per animation including more control
 * parameters as for example:
 *
 * - brightnes control per action
 * - speed wipes per action, which would reduce the number
 *   of actions to be defined for seamless speed changes
 *
 * as i designed this for the gemma hoops as suggested on adafruit's web page
 * there seems to be no suitable way of connecting an external storage device
 * 
 ******************************************************************************/

#include <Adafruit_NeoPixel.h>

/******************************************************************************
 *
 * where the action list is to be declared and all animation actions 
 * are to be defined:
 *
 ******************************************************************************/

#include "GemmaHoopActionList.h"
 
/******************************************************************************
 *
 * general global variables
 *
 ******************************************************************************/

uint32_t color = 0, 
         color_timer = 0, 
         action_timer = 0, 
         action_step_timer = 0;
uint16_t color_idx = 0, 
         curr_color_interval = 0, 
         curr_action_step_duration = 0, 
         curr_action_duration = 0;
uint8_t  spectrum_part = 0, 
         curr_action = 0, 
         curr_color_gen = COL_RANDOM, 
         idx = 0, 
         offset = 0, 
         number_of_actions = 0, 
         curr_action_idx = 0, 
         curr_color_granularity = 1;

/******************************************************************************
 *
 * general global variables
 *
 ******************************************************************************/

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, PIXEL_OUTPUT);

/******************************************************************************
 *
 * initializing - note that the action list is declared and initialized
 * in GemmaHoopActionList.h!
 *
 ******************************************************************************/

void setup() 
{
  // fingers corssed, the seeding makes sense to really get random colors...
  randomSeed(analogRead(ANALOG_INPUT));  
  
  // we need to know, how many actions are defined - shall the there be too
  // many actions defined, the RAM will overflow and he µC won't do anything
  // --> rather easy diagnosis ;-)
  number_of_actions = sizeof (theActionList) / sizeof (actiondesc);
  
  // let's go!
  pixels.begin();
  pixels.setBrightness(BRIGHTNESS);
  nextColor();
  pixels.show();
}

/******************************************************************************
 *
 * where all the magic happens - note that the action list is declared and 
 * initialized in GemmaHoopActionList.h!
 *
 ******************************************************************************/

void loop() 
{
  // do we need to load the next action?
  if ((millis() - action_timer) > curr_action_duration)
  {
    curr_action_duration = theActionList[curr_action_idx].action_duration;
    curr_action = theActionList[curr_action_idx].action_and_color_gen & 0b00111111;
    curr_action_step_duration = theActionList[curr_action_idx].action_step_duration;
    curr_color_gen = theActionList[curr_action_idx].action_and_color_gen & 0b11000000;
    curr_color_granularity = theActionList[curr_action_idx].color_granularity;
    curr_color_interval = theActionList[curr_action_idx].color_interval;
    
    curr_action_idx++;
    // take care to rotate the action list!
    curr_action_idx %= number_of_actions; 

    action_timer = millis();
  }
  
  // do we need to change to the next color?
  if ((millis() - color_timer) > curr_color_interval)
  {
    nextColor();
    color_timer = millis();
  }
  
  // do we need to step up the current action?
  if ((millis() - action_step_timer) > curr_action_step_duration)
  {
    switch (curr_action)
    {
      case ACT_NOP :
      {
        // rather trivial even tho this will be repeated as long as the
        // NOP continues - i could have prevented it from repeating
        // unnecessarily, but that would mean more code and less
        // space for more actions within the animation
        for (int i = 0; i < NUM_PIXELS; i++) {
          pixels.setPixelColor(i,0);
          pixels.setPixelColor((NUM_PIXELS*2)-1-i,color);
        }
        break;
      }
      case ACT_SIMPLE_RING :
      {
        // even more trivial - just set the new color, if there is one
        for (int i = 0; i < NUM_PIXELS; i++) {
          pixels.setPixelColor(i,color);
          pixels.setPixelColor((NUM_PIXELS*2)-1-i,color);
        }
        break;
      }
      case ACT_CYCLING_RING_ACLK :
      case ACT_CYCLING_RING_CLKW :
      {
        // spin the ring clockwise or anti clockwise
        (curr_action == ACT_CYCLING_RING_ACLK) ? idx++ : idx--;
        // prevent overflows or underflows
        idx %= NUM_PIXELS;
        // set the new color, if there is one
        pixels.setPixelColor(idx,color);
        pixels.setPixelColor((NUM_PIXELS*2)-1-idx,color);
        break;
      }
      case ACT_WHEEL_ACLK :
      case ACT_WHEEL_CLKW :
      {
        // switch on / off the appropriate pixels according to
        // the current offset
        for(idx=0; idx < NUM_PIXELS; idx++) 
        {
          pixels.setPixelColor(idx, ((offset + idx) & 7) < 2 ? color : 0);
          pixels.setPixelColor((NUM_PIXELS*2)-1-idx, ((offset + idx) & 7) < 2 ? color : 0);
        }
        // advance the offset and thus, spin the wheel
        // clockwise or anti clockwise
        (curr_action == ACT_WHEEL_CLKW) ? offset++ : offset--;
        // prevent overflows or underflows
        offset %= NUM_PIXELS;
        break;
      }
      case ACT_SPARKLING_RING :
      {
        // switch current pixel off
        pixels.setPixelColor(idx,0);
        pixels.setPixelColor((NUM_PIXELS*2)-1-idx,0);
        // pick a new pixel
        idx = random (NUM_PIXELS);
        // set new pixel to the current color
        pixels.setPixelColor(idx,color);
        pixels.setPixelColor((NUM_PIXELS*2)-1-idx,color);
        break;
      }
/*    for the sake of free RAM we disobey the rules
      of consistent coding and leave the following
      
      default :
      {
      }
*/      
    }
    pixels.show();
    action_step_timer = millis();
  }    
}

void nextColor ()
{
/*
 * detailed color generation method selection is obsolete
 * as long as there are just two methods
 
  switch (curr_color_gen)
  {
    case COL_RANDOM :
    {
      nextRandomColor();
      break;
    }
    case COL_SPECTRUM :
    {
      nextSpectrumColor();
      break;
    }
    default :
    {
    }
  }

 */
 
 // save some RAM for more animation actions
 (curr_color_gen & COL_RANDOM) ? nextRandomColor() : nextSpectrumColor();
}

void nextSpectrumColor ()
{
  switch (spectrum_part)
  {
    case 0 :  // spectral wipe from red to blue
    {
      color = Adafruit_NeoPixel::Color(255-color_idx,color_idx,0);
      color_idx += curr_color_granularity;
      if (color_idx > 255) 
      {
          spectrum_part = 1;
          color_idx = 0;
      }
      break;
    }
    case 1 :  // spectral wipe from blue to green
    {
      color = Adafruit_NeoPixel::Color(0,255-color_idx,color_idx);
      color_idx += curr_color_granularity;
      if (color_idx > 255) 
      {
          spectrum_part = 2;
          color_idx = 0;
      }
      break;
    }
    case 2 :  // spectral wipe from green to red
    {
      color = Adafruit_NeoPixel::Color(color_idx,0,255-color_idx);
      color_idx += curr_color_granularity;
      if (color_idx > 255) 
      {
          spectrum_part = 0;
          color_idx = 0;
      }
      break;
    }
/*  for the sake of free RAM we disobey the rules
    of consistent coding and leave the following
    
    default :
    {
    }
*/      
  }
}

void nextRandomColor ()
{
  color = Adafruit_NeoPixel::Color(random(256/curr_color_granularity) * curr_color_granularity,
                                   // granularity = 1 --> [0 .. 255] * 1 --> 0,1,2,3 ... 255
                                   random(256/curr_color_granularity) * curr_color_granularity,
                                   // granularity = 10 --> [0 .. 25] * 10 --> 0,10,20,30 ... 250
                                   random(256/curr_color_granularity) * curr_color_granularity);
                                   // granularity = 100 --> [0 .. 2] * 100 --> 0,100, 200 (boaring...)
}
Inverse code Explained.
You may notice the following line in the code above: pixels.setPixelColor(idx,color);
That line draws one pixel position on the ring, where 'dix' is the pixel number, and 'color' is the color it's being set to.

To display the inverse, we'll need to draw another pixel at the same time, to match the color, so I simply added another identical line below the first one, everywhere it occurred. To get the mirrored pixel, we need to play with the pixel number, in this case, variable 'idx'.

I replaced this position with (NUM_PIXELS*2)-1-idx. See what it does?
When ever it is set to color pixel 0 red, it will also set pixel (16*2)-1-0 == 31 to red as well (which is the opposite side of the second ring), and so on.
If you have 16 pixels, they are represented as 0-15.

Go ahead and try this and let me know if it's what you were wanting. :)

Johno2000
 
Posts: 11
Joined: Tue Jun 03, 2014 9:58 pm

Re: Gemma Hoop help

Post by Johno2000 »

SeiRruf thank you for your message, the code makes more sense and you understand what I want it to do. I have used this code, but the second rind does not light up?

User avatar
SeiRruf
 
Posts: 82
Joined: Thu Sep 04, 2014 3:07 am

Re: Gemma Hoop help

Post by SeiRruf »

Please make sure your wiring is correct.

One ring should have data in plugged into your arduino, and its data out wired into the data in of the second ring. Both rings share +5v and Gnd, so don't forget to wire those as well.

In your GammaHoopActionList.h file, set 'NUM_PIXEL' to only 16 (one ring). The code I provided automatically assumes there will be two rings, and will only draw animations for one ring, and mirror them on a second one.

If you are uncertain, please post a clear photo of your current wiring, if you are still having troubles.

Johno2000
 
Posts: 11
Joined: Tue Jun 03, 2014 9:58 pm

Re: Gemma Hoop help

Post by Johno2000 »

Thankyou again SeiRruf. I have been trying to troubleshoot and I still have a problem =/

I am using the code as posted.
I have checked the gemmahoopactionlist.h file says 16 for Num_pixel.
I have wired up both grounds and +5v on each ring to the correct pads on the gemma, gnd and vout.
I have gemma pad D0 wired onto the input of 1st ring, output of first ring to input of second ring.
All contacts have been double and tripple checked

What happens is the 1st ring works, but the second does not?

I have swapped the rings and used new rings, and used a new gemma, but all parts are working and the same result each time, 1st ring working, second not... I am very puzzled?? =S

I have also tried changing Pixel_output 0 to Pixel_output 1 in the gemahoopactionlist.h file to see if it needed to use a different pad. But i get the same results.

Locked
Please be positive and constructive with your questions and comments.

Return to “Wearables”