Archive for the ‘Level 2’ Category

Driving Multiple Digit Shields from One Arduino

Difficulty Level = 2 [What’s this?]

The Digit Shield is a very easy-to-use Arduino shield that provides a digital readout for your Arduino projects. Some example projects are here.

One of my customers asked me about driving multiple Digit Shields from one Arduino. I had never thought of that, but the customer had the idea of using a single Arduino to display the X,Y,Z positions of a CNC router. I thought this was an intriguing idea, and with a little bit of experimentation and modification to the Digit Shield library, I was able to very easily accomplish this.

Driving multiple Digit Shields with one Arduino


 

When a Digit Shield is on top of an Arduino, the pins used to control the shield are 2, 3, 4, and 5. In the picture above, this shield is displaying value “60.08”. If we connect another shield, we obviously have to use different Arduino pins to drive it. The second shield in the picture above (the one displaying “59”) is connected to Arduino pins 6, 7, 8, and 9. Of course, the wires still connect to pins 2, 3, 4, and 5 on the shield itself.

The 3rd shield in the picture displaying “1800” has its pins 2, 3, 4, and 5 connected to Arduino pins A3, A2, A1, and A0 respectively. In the code, analog pins are used as digital pins by referring to them as 17, 16, 15, and 14.

What about the code? I added a constructor for DigitShieldClass to the library so you can create new objects to represent the additional shields. The shield on the Arduino is still referenced as “DigitShield”, but the additional ones are referenced as “digitShield2” and “digitShield3”. Here’s how the shields are declared and initialized.

// Create a second Digit Shield connected to Arduino pins 6,7,8,9                            
// Connected to pins 2,3,4,5 on the shield, respectively.                                    
DigitShieldClass digitShield2(6, 7, 8, 9);

// Create a third Digit Shield connected to Arduino pins 17,16,15,14 (A3,A2,A1,A0)           
// Connected to pins 2,3,4,5 on the shield, respectively.                                    
DigitShieldClass digitShield3(17, 16, 15, 14);

void setup() {
  // The static variable DigitShield refers to the default                                   
  // Digit Shield that is directly on top of the Arduino                                     
  DigitShield.begin();
  DigitShield.setPrecision(2);

  // Initialize the other two shields                                                        
  digitShield2.begin();
  digitShield3.begin();

  // set all values to 0
  DigitShield.setValue(0);
  digitShield2.setValue(0);
  digitShield3.setValue(0);
}

The full code example is called “MultiShieldExample” and is included in the Digit Shield library.

Also note that I’m providing power to the off-Arduino shields with a 7805 voltage regulator. The Arduino’s voltage regulator can deliver quite a bit of power, but it got rather warm when driving all these LEDs. So, in the picture above, there’s a 7805 which provides 5V to the 5V pins on the off-Arduino shields. Also make sure you connect all the grounds together.


Published by Michael, on May 21st, 2011 at 10:09 am. Filed under: Arduino,Level 2. | 2 Comments |

Text and Graphics Overlay on Video

Difficulty Level = 2 [What’s this?]

The Video Experimenter shield makes it easy to overlay text and graphics onto any composite video signal. Any source of composite video should work — video camera, VCR, DVD player, DVR, cable box, etc.

Text and graphics overlayed onto a TV signal.

 

Video Experimenter projects require an enhanced version of the TVout library which can be downloaded here. All of the usual TVout drawing primitives can be used to add text or graphics to the screen. Here’s a video of a demo where I had the output of a VCR connected to the Video Experimenter input, then the Video Experimenter output connected to my TV.

 
Download the OverlayDemo sketch here. Your sketchbook structure should look like this:

Arduino
    |
    +--OverlayDemo
    |         |
    |         +--OverlayDemo.pde
    |
    +--libraries
              |
              +--TVout
              |     |
              |     +--...many files
              |
              +--TVoutfonts
                    |
                    +--...many files

Here’s the OverlayDemo sketch source code. If you use a television with the PAL standard (that is, you are not in North America), change tv.begin(NTSC, W, H) to tv.begin(PAL, W, H).

#include <TVout.h>
#include <fontALL.h>

#define W 136
#define H 96

TVout tv;
unsigned char x,y;
unsigned char originx = 5;
unsigned char originy = 80;
unsigned char plotx = originx;
unsigned char ploty = 40;
char s[32];
unsigned int n = 0;
int index = 0;
int messageLen = 32;
char message[] = "...OVERLAY TEXT AND GRAPHICS ON A VIDEO SIGNAL...OVERLAY TEXT AND GRAPHICS ON A VIDEO SIGNAL";
char saveChar;

void setup()  {
  tv.begin(NTSC, W, H);
  initOverlay();
  tv.select_font(font6x8);
  tv.fill(0);
  drawGraph();
  randomSeed(analogRead(0));
}
// Initialize ATMega registers for video overlay capability.
// Must be called after tv.begin().
void initOverlay() {
  TCCR1A = 0;
  // Enable timer1.  ICES0 is set to 0 for falling edge detection on input capture pin.
  TCCR1B = _BV(CS10);

  // Enable input capture interrupt
  TIMSK1 |= _BV(ICIE1);

  // Enable external interrupt INT0 on pin 2 with falling edge.
  EIMSK = _BV(INT0);
  EICRA = _BV(ISC01);
}

// Required to reset the scan line when the vertical sync occurs
ISR(INT0_vect) {
  display.scanLine = 0;
}


void loop() {
  saveChar = message[index+22];
  message[index+22] = '\0';

  for(int x=6;x>=0;x--) {
    if (x<6) {
      tv.delay_frame(1);
    }
    tv.print(x, 87, message+index);

    for(byte y=87;y<96;y++) {
      tv.draw_line(0, y, 5, y, 0);
      tv.draw_line(128, y, 134, y, 0);
    }
  }
  message[index+22] = saveChar;
  index++;
  if (index > 45) {
    index = 0;
  }

  sprintf(s, "%dms", millis());
  tv.print(0, 0, s);


  if (plotx++ > 120) {
    tv.fill(0);
    drawGraph();
    plotx = originx + 1;
    return;
  }
  byte newploty = ploty + random(0, 7) - 3;
  newploty = constrain(newploty, 15, originy);
  tv.draw_line(plotx-1, ploty, plotx, newploty, 1);
  ploty = newploty;
}

void drawGraph() {
  tv.draw_line(originx, 15, originx, originy, 1);
  tv.draw_line(originx, originy, 120, originy, 1);
  for(byte y=originy;y>15;y -= 4) {
    tv.set_pixel(originx-1, y, 1);
    tv.set_pixel(originx-2, y, 1);
  }
  for(byte x=originx;x<120;x += 4) {
    tv.set_pixel(x, originy+1, 1);
    tv.set_pixel(x, originy+2, 1);
  }
}



Published by Michael, on March 20th, 2011 at 12:45 pm. Filed under: Arduino,Level 2,Video. | 59 Comments |