Board Diagnostics

A sketch to test newly assembled boards.  Open the Serial Monitor at 115200 baud to get a walkthrough as you test.

#include <Servo.h> 

/* Rotary encoder read example */
#define ENCODER_A 14
#define ENCODER_B 15
#define ENCODER_PORT PINC
#define SWITCH 13
#define BUTTON 12
#define RGB_RED 11
#define RGB_GREEN 10
#define RGB_BLUE 9
#define LED 6
#define SERVO 5
#define PIEZO 3
#define RELAY 2
#define POT 2
#define HALL 3
#define THERMISTOR 4
#define PHOTOCELL 5


Servo myservo;  // create servo object to control a servo 

void setup()
{
 /* Setup encoder pins as inputs */
 pinMode(ENCODER_A, INPUT);
 digitalWrite(ENCODER_A, HIGH);
 pinMode(ENCODER_B, INPUT);
 digitalWrite(ENCODER_B, HIGH);
 pinMode(SWITCH, INPUT);
 pinMode(BUTTON, INPUT);
 pinMode(RGB_RED, OUTPUT);
 pinMode(RGB_BLUE, OUTPUT);
 pinMode(RGB_GREEN, OUTPUT);
 pinMode(LED, OUTPUT);
 pinMode(PIEZO, OUTPUT);
 pinMode(RELAY, OUTPUT);

 Serial.begin (115200);
  Serial.println("");
  Serial.println("");
 Serial.println("Begin diagnostic");
}

void loop() {
  testDigitalIn("Switch", SWITCH);
  testDigitalIn("Button", BUTTON);
  
  testDigitalOut("LED", LED);
  testDigitalOut("Red", RGB_RED);
  testDigitalOut("Green", RGB_GREEN);
  testDigitalOut("Blue", RGB_BLUE);
  testAnalogOut("Piezo", PIEZO);
  testDigitalOut("Relay", RELAY);

  testServo();
  
  testAnalogIn("Light Sensor", PHOTOCELL);
  testAnalogIn("Hall Sensor", HALL);
  testAnalogIn("Thermistor", THERMISTOR);
  testAnalogIn("Potentiometer", POT);
  
  testRotary();
}

void testDigitalOut(String name, int pin) {
  Serial.println("Testing: " + name);
  digitalWrite(pin, HIGH);
  delay(800);
  digitalWrite(pin, LOW);
  delay(200);
}

void testAnalogOut(String name, int pin) {
  Serial.println("Testing: " + name);
  analogWrite(pin, 128);
  delay(800);
  digitalWrite(pin, LOW);
  delay(200);
}  

void testServo() {
  myservo.attach(SERVO);
  delay(100);
  Serial.println("Testing: Servo");
  myservo.write(45);
  delay(700);
  myservo.write(135);
  delay(700);
  myservo.detach(); 
}

void testDigitalIn(String name, int pin) {
  int startValue = digitalRead(pin);
  int newValue = startValue;
  Serial.println("Testing: " + name + ". Change value to continue...");
  while (startValue == newValue) {
   newValue = digitalRead(pin);
   delay(40);
  }
  analogWrite(PIEZO, 128);
  delay(100);
  digitalWrite(PIEZO, LOW);
  delay(200);
}

void testAnalogIn(String name, int pin) {
  int startValue = analogRead(pin);
  int delta = 0;
  Serial.println("Testing: " + name + ". Change value to continue...");
  while (delta < 20) {
   delta = abs(startValue - analogRead(pin));
   delay(40);
  }
  analogWrite(PIEZO, 128);
  delay(100);
  digitalWrite(PIEZO, LOW);
}

void testRotary() {
  Serial.println("Testing: Rotary Encoder. Change value to continue...");
  int8_t startData = 0;
  while (abs(startData) < 12) {
    startData += read_encoder();
  }
  analogWrite(PIEZO, 128);
  delay(100);
  digitalWrite(PIEZO, LOW);
}

int8_t read_encoder()
{
    static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
    static uint8_t old_AB = 0;
    old_AB <<= 2;                   //remember previous state
    old_AB |= ( ENCODER_PORT & 0x03 );  //add current state
    return ( enc_states[( old_AB & 0x0f )]);
}

									

Alternative Diagnostics. Runs through all the functionality one by one.

#include <Servo.h> 

/* Rotary encoder read example */
#define ENCODER_A 14
#define ENCODER_B 15
#define ENCODER_PORT PINC
#define SWITCH 13
#define BUTTON 12
#define RGB_RED 11
#define RGB_GREEN 10
#define RGB_BLUE 9
#define LED 6
#define SERVO 5
#define PIEZO 3
#define RELAY 2
#define POT 2
#define HALL 3
#define THERMISTOR 4
#define PHOTOCELL 5

/* 
CodeShield Diagnostic V0.2 Dave Carpenter 
Designed to test all inputs and outputs
Any components not working or disconnected will not stall the diagnostic.
Current step can be skipped by pressing the button or wait until the step 
is completed.

Set a serial monitor at 115200 baud to see diagnostics of the current step.
Switch controls whether piezo will beep and whether servo will move.
All outputs are affected by each test:
 LED1's brightness
 LED2's colour
 PIEZO's tone
 SERVO's angle
 RELAY's state

Tests adjust all of the outputs depending on the input:
1) Waveform: no input test of outputs
2) Thermistor: hold THERM component to change outputs by temperature
3) Hall effect: bring a magnet near HALL component to change outputs by field
4) Photocell: cover or illuminate PHOTO to change outputs by light
5) Potentiometer: turn POT handle to vary outputs continuously
6) Encoder: turn ENC handle to step outputs up and down in steps

BUTTON is used to skip to the next test before it is finished
SWITCH will turn off the piezo and servo so you can hear the relay changing state

**** TO FIX: encoder skips many steps
   Piezo is "phasing" instead of changing tone
   Servo being on also seems to mangle the colours on LED2, perhaps too much drain on the usb power?
*/

static boolean showValues = false; //set to true to see the input values
   // on the serial output

Servo myservo;  // create servo object to control a servo 
static uint8_t counter = 1;      //this variable will be changed by encoder input
int switchState = LOW;
int lastRotValue;
int testState = -1;
int testCount = -1;
static int testValue;
int rawValue;
String testInfo[] = {
 "Waveform: no input test of outputs", 
 "Thermistor: hold THERM component to change outputs by temperature",
 "Hall effect: bring a magnet near HALL component to change outputs by field",
 "Photocell: cover or illuminate PHOTO to change outputs by light",
 "Potentiometer: turn POT handle to vary outputs continuously",
 "Encoder: turn ENC handle to step outputs up and down in steps"
};

void setup()
{
 /* Setup encoder pins as inputs */
 pinMode(ENCODER_A, INPUT);
 digitalWrite(ENCODER_A, HIGH);
 pinMode(ENCODER_B, INPUT);
 digitalWrite(ENCODER_B, HIGH);
 pinMode(SWITCH, INPUT);
 pinMode(BUTTON, INPUT);
 pinMode(RGB_RED, OUTPUT);
 pinMode(RGB_BLUE, OUTPUT);
 pinMode(RGB_GREEN, OUTPUT);
 pinMode(LED, OUTPUT);
 pinMode(PIEZO, OUTPUT);
 pinMode(RELAY, OUTPUT);

 Serial.begin (115200);
 Serial.println("Begin diagnostic");
}

void loop() {

 testCount = (testCount + 1) % 256;
 if(!testCount) { 
     testState = (testState + 1) % 6;
     Serial.println("Test "+String(testState)+": " + testInfo[testState]);
    if(showValues) {
       delay(1500); //pause or you can't read it when values fly past
     }

     testValue = 0; //set a default, e.g. for encoder step
 }
 switch (testState) {
   case 0: // waveform (no input) test
     rawValue = testCount;
     testValue = rawValue;
     break;
   case 1: // thermistor test
     rawValue = analogRead(THERMISTOR);
     testValue = constrain(map(rawValue, 500, 600, 0, 255),0,255);
     break;
   case 2: // hall effect
     rawValue = analogRead(HALL);
     testValue = constrain(map(rawValue,400,600,0,255),0,255);
     break;
   case 3: // photocell 
     rawValue = analogRead(PHOTOCELL);
     testValue = constrain(map(rawValue,400,800,0,255),0,255);
     break;
   case 4: // pot
     rawValue = analogRead(POT);
     testValue = constrain(map(rawValue,150,600,0,255),0,255);
     break;
   case 5: // encoder
     //step up or down by steps of 16 based on encoder
     rawValue = read_encoder();
     testValue = testValue + rawValue*16; 
     break;
 }

 if(showValues) {
   Serial.println("Raw: " + String(rawValue) + 
     " Test: " + String(testValue) +
     " Button: " + String(digitalRead(BUTTON)==HIGH) +
     " Switch: " + String(digitalRead(SWITCH)==HIGH)
   );
 }

 //LED 1 brightness is testValue
 analogWrite(LED, (testValue)%256);

 //LED 2 testValue is transformed to a colour spectrum of red, yellow, green,
 // cyan, blue, magenta, red 
 analogWrite(RGB_RED, (testValue<85)*(85-testValue)*3 + (testValue>=170)*(testValue%85)*3 + (testValue==255)*255);
 analogWrite(RGB_GREEN, (testValue<85)*(testValue)*3 + (testValue>=85 && testValue<170)*(85-(testValue%85))*3);
 analogWrite(RGB_BLUE, (testValue>=170 && testValue<255)*(85-(testValue%85))*3 + (testValue>=85 && testValue<170)*(testValue%85)*3);

 //Relay state is testValue low or high; should be able to hear clicking
 digitalWrite(RELAY, (testValue<128));

 //Piezo is 
 analogWrite(PIEZO, testValue*digitalRead(SWITCH)); // don't make a tone if switch is off

 //Servo angle mapped to testValue if switch is on
 if (digitalRead(SWITCH) == HIGH) {
   myservo.attach(SERVO);
   myservo.write(map(testValue, 0, 255, 0, 179));    
 } else {
   myservo.detach();
 } 

 while(digitalRead(BUTTON)==HIGH) {
   testCount=255; //start next test
 } //put this in a while so we don't skip five tests for one "press"

 delay(50);
}

/* returns change in encoder state (-1,0,1) */
int8_t read_encoder()
{
 static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
 static uint8_t old_AB = 0;
 /**/
 old_AB <<= 2;                   //remember previous state
 old_AB |= ( ENCODER_PORT & 0x03 );  //add current state
 return ( enc_states[( old_AB & 0x0f )]);
}
									

2 comments. Leave a Reply

Leave a Reply

Your email is never published nor shared.

You may use these HTML tags and attributes:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>