├── BornVernierHalfLifeSimulator └── BornVernierHalfLifeSimulator.ino ├── LICENSE.md ├── README.md ├── Vernier3DAAutoscale └── Vernier3DAAutoscale.ino ├── VernierAnalogSensorThreshold └── VernierAnalogSensorThreshold.ino ├── VernierBirthdayCandle └── VernierBirthdayCandle.ino ├── VernierCount └── VernierCount.ino ├── VernierDigitalAutoID └── VernierDigitalAutoID.ino ├── VernierFreq_Motion └── VernierFreq_Motion.ino ├── VernierFrequency └── VernierFrequency.ino ├── VernierHandControl1 └── VernierHandControl1.ino ├── VernierHandControl2 └── VernierHandControl2.ino ├── VernierHandControl4-1 └── VernierHandControl4-1.ino ├── VernierHandControl4-2 └── VernierHandControl4-2.ino ├── VernierISE └── VernierISE.ino ├── VernierLaserTracker └── VernierLaserTracker.ino ├── VernierLaserTrackerAutoOn └── VernierLaserTrackerAutoOn.ino ├── VernierLibDemo └── VernierLibDemo.ino ├── VernierLibDemoDCU └── VernierLibDemoDCU.ino ├── VernierLibDemoMotionDetector └── VernierLibDemoMotionDetector.ino ├── VernierMotionDetector └── VernierMotionDetector.ino ├── VernierMotionDetectorThreshold └── VernierMotionDetectorThreshold.ino ├── VernierMousetrap └── VernierMousetrap.ino ├── VernierPendulumDriver └── VernierPendulumDriver.ino ├── VernierPhotogate └── VernierPhotogate.ino ├── VernierPingPongPID └── VernierPingPongPID.ino ├── VernierRadiation └── VernierRadiation.ino ├── VernierRotary └── VernierRotary.ino ├── VernierServo └── VernierServo.ino ├── VernierThermistor └── VernierThermistor.ino ├── VernierThermistorDisplay └── VernierThermistorDisplay.ino ├── VernierThermistorStore └── VernierThermistorStore.ino └── libraries ├── PID ├── PID_v1.cpp ├── PID_v1.h ├── README.txt ├── examples │ ├── PID_AdaptiveTunings │ │ └── PID_AdaptiveTunings.ino │ ├── PID_Basic │ │ └── PID_Basic.ino │ ├── PID_PonM │ │ └── PID_PonM.ino │ └── PID_RelayOutput │ │ └── PID_RelayOutput.ino ├── keywords.txt ├── library.json └── library.properties └── readme.txt /BornVernierHalfLifeSimulator/BornVernierHalfLifeSimulator.ino: -------------------------------------------------------------------------------- 1 | /* Radioactive Decay Half-Life Simulator 2 | by Richard Born on May 31, 2015 3 | with modifications suggestions by Dave Vernier */ 4 | 5 | int decayOUT = 6; // output from Digital 2 port on Vernier Sensor Interface Shield to Vernier Interface (e.g., LabQuest 2) 6 | int decayLED = 13; // pin 13 on the Vernier Shield will flash when a simulated atom decays 7 | float clock = 0; // simulation clock 8 | int startRate; // initial decay rate in decays per second 9 | float rate; // decay rate at simulation 'clock' time 10 | float reciprocalRate; // time between decays in seconds 11 | float sign; // will be either 1 or -1 to provide some random variation in time between decays // 12 | float lambda; // decay constant 13 | int beginRate[] = {11, 23, 32}; // decays per second (one of these three is randomly selected on each run of the sketch 14 | float decayConstant[] = {0.0125, 0.00625, 0.00357, 0.00227}; // one of these four is randomly selected on each run of the sketch 15 | 16 | void setup() { 17 | 18 | // declare pin modes 19 | pinMode(decayOUT, OUTPUT); 20 | pinMode(decayLED, OUTPUT); 21 | randomSeed(analogRead(10)); // need to use an unused pin on the Vernier Interface Shield to provide randomness 22 | // even though 10 is digital, analogRead of this pin seems to provide 23 | // for random results on each run of the sketch 24 | startRate = beginRate[random(0,3)]; // randomly select one of the three initial decay rates 25 | lambda = decayConstant[random(0,4)]; // randomly select on the the 4 decay constants 26 | 27 | } 28 | 29 | void loop() { 30 | 31 | rate = startRate*exp(-lambda*clock); // get decay rate at 'clock' time 32 | reciprocalRate = 1/rate; // get time between decays 33 | // sign will be 1 about 50% of the time and 0 the remaining 50% 34 | if (random(0,2) == 0) { 35 | sign = -1; // will decrease the reciprocal rate randomly 36 | } else { 37 | sign = 1; // will increaes the reciprocal rate randomly 38 | } 39 | // The following will vary the reciprocal rate an average of 20% 40 | // with a minimum of 0% and a maximum of 40% 41 | reciprocalRate *= 1.0 + sign * (float(random(2000))/5000.0); 42 | digitalWrite(decayLED, HIGH); // turn on the decay LED 43 | digitalWrite(decayOUT, HIGH); // send signal to Vernier interface via pin 6 44 | delay(1); // slight pause while LED is ON 45 | digitalWrite(decayLED, LOW); // turn off the decay LED 46 | digitalWrite(decayOUT, LOW); // lower the signal to the Vernier interface 47 | delay(reciprocalRate*1000); // delay the simulation by an amount equal to the time between decays 48 | clock += reciprocalRate; // increaase the simulation clock by the time between decays 49 | 50 | } 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Vernier Software & Technology 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | http://opensource.org/licenses/MIT -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Using Arduino and Vernier Sensors 2 | ======== 3 | 4 | Overview 5 | -------- 6 | 7 | Vernier has always supported hands-on, do-it-yourself projects for students (or teachers). The availability of very inexpensive, easy-to-program microcomputers, 8 | like the Arduino, makes projects easy and affordable. 9 | 10 | We posted a guide to [Using Vernier sensors with Arduino][1]. It is a free guide to connecting, calibrating, writing programs, and doing fun projects with our sensors. 11 | The guide references sketches included in this repository. 12 | 13 | All sketches are developed by Vernier. 14 | 15 | Include the [VernierLib library][2] in your version of the Arduino IDE to make using Vernier sensors easy. 16 | 17 | 18 | License 19 | ------- 20 | 21 | This projected is licensed under the terms of the [MIT license][3]. 22 | 23 | [1]: http://www.vernier.com/arduino/ 24 | [2]: https://github.com/VernierSoftwareTechnology/VernierLib 25 | [3]: http://opensource.org/licenses/MIT -------------------------------------------------------------------------------- /Vernier3DAAutoscale/Vernier3DAAutoscale.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Vernier3DA (v 2017.08) 3 | This project assumes that you have a Vernier 3D Accelerometer connected to 4 | three BTA connectors. It also assumes that you have an RGB LED connected to 5 | PWM outputs 3, 5, and 6. 6 | 7 | Plug x into the first BTA (A0), y into the second BTA (A2), and z into 8 | the third BTA (A4). 9 | The brightness of the red LED is controlled by the x axis acceleration. 10 | The brightness of the green LED is controlled by the y axis acceleration. 11 | The brightness of the blue LED is controlled by the z axis acceleration. 12 | 13 | During the first 15 seconds of this program you should rotate the 14 | accelerometer through all 3 axes. This will calibrate the signal for 15 | you specific accelerometer. If you do not rotate the sensor it will 16 | default to set values. All LEDs will flash for 1 second at the beginning 17 | and end of this "calibration". 18 | After calibration, each color should progress through a range of "off" to 19 | full power based on the orientation of the accelerometer. Sitting flat on a 20 | surface (z-axis up) is blue, flat on its side (y-axis up) is green, and cord 21 | facing down is red. 22 | Note that either individual LEDs or a RGB LED may be used. 23 | 24 | See www.vernier.com/arduino for more information. 25 | */ 26 | const int RedPin = 3; 27 | const int GreenPin = 5; 28 | const int BluePin = 6; 29 | 30 | const int sensorPinRed = A0; 31 | const int sensorPinGreen = A2; 32 | const int sensorPinBlue = A4; 33 | 34 | int var = 1; 35 | int minReadingRed = 450; // Default value if no calibration 36 | int maxReadingRed = 600; // Default value if no calibration 37 | int minReadingGreen = 450; 38 | int maxReadingGreen = 600; 39 | int minReadingBlue = 500; 40 | int maxReadingBlue = 830; 41 | 42 | int analogValueR = 0; 43 | int analogValueG = 0; 44 | int analogValueB = 0; 45 | int time; 46 | int analogOut; 47 | 48 | void setup() 49 | { 50 | Serial.begin(9600); 51 | 52 | } 53 | void loop() 54 | { 55 | while (time < 1000){ // LEDs to flash at start of calibration 56 | time = millis(); 57 | analogWrite(RedPin, 255); 58 | analogWrite(GreenPin, 255); 59 | analogWrite(BluePin, 255); 60 | delay (1000); 61 | analogWrite(RedPin, 0); 62 | analogWrite(GreenPin, 0); 63 | analogWrite(BluePin, 0); 64 | delay (10);} 65 | while (time>1000 && time < 16000){ 66 | time = millis(); 67 | // Time to calibrate each sensor to it's particular range of values. 68 | //Red 69 | analogValueR = analogRead(sensorPinRed); 70 | maxReadingRed = max(analogValueR, maxReadingRed); 71 | minReadingRed = min(analogValueR, minReadingRed);// This is the absolute min. We'll adjust this up 72 | //Green 73 | analogValueG = analogRead(sensorPinGreen); 74 | maxReadingGreen = max(analogValueG, maxReadingGreen); 75 | minReadingGreen = min(analogValueG, minReadingGreen);// This is the absolute min. We'll adjust this up 76 | //Blue 77 | analogValueB = analogRead(sensorPinBlue); 78 | maxReadingBlue = max(analogValueB, maxReadingBlue); 79 | minReadingBlue = min(analogValueB, minReadingBlue);// This is the absolute min. We'll adjust this up 80 | } 81 | while(time > 16000 && time < 17000){ // LEDs to flash at finish of calibration 82 | time = millis(); 83 | Serial.print(minReadingRed); 84 | Serial.print("/t"); 85 | Serial.println(maxReadingRed); 86 | analogWrite(RedPin, 255); 87 | analogWrite(GreenPin, 255); 88 | analogWrite(BluePin, 255); 89 | delay (1000); 90 | analogWrite(RedPin, 0); 91 | analogWrite(GreenPin, 0); 92 | analogWrite(BluePin, 0);} 93 | 94 | while (var == 1){ 95 | minReadingRed = minReadingRed+0.25*(maxReadingRed - minReadingRed); // Adjusts minimum value (experiment with factor) 96 | minReadingGreen = minReadingGreen+0.25*(maxReadingGreen - minReadingGreen); 97 | minReadingBlue = minReadingBlue+0.25*(maxReadingBlue - minReadingBlue); 98 | 99 | Serial.println();//prints range of each axis 100 | Serial.print("minReadingRed = " ); 101 | Serial.print(minReadingRed, DEC); 102 | Serial.print(" maxReadingRed = " ); 103 | Serial.println(maxReadingRed, DEC); 104 | Serial.print("minReadingGreen = " ); 105 | Serial.print(minReadingGreen, DEC); 106 | Serial.print(" maxReadingGreen = " ); 107 | Serial.println(maxReadingGreen, DEC); 108 | Serial.print("minReadingBlue = " ); 109 | Serial.print(minReadingBlue, DEC); 110 | Serial.print(" maxReadingBlue = " ); 111 | Serial.println(maxReadingBlue, DEC); 112 | var = 2; 113 | } 114 | // Below is scrolling printout 115 | 116 | //Red 117 | analogValueR = analogRead(sensorPinRed); 118 | analogValueR = constrain(analogValueR, minReadingRed, maxReadingRed); 119 | Serial.print("analogValue Red = " ); 120 | Serial.println(analogValueR); 121 | analogOut = map(analogValueR, minReadingRed, maxReadingRed, 0, 255); 122 | analogOut = constrain(analogOut, 0, 255); 123 | Serial.print(" scaled to " ); 124 | Serial.println(analogOut, DEC); 125 | analogWrite(RedPin, analogOut); 126 | 127 | //Green 128 | analogValueG = analogRead(sensorPinGreen); 129 | analogValueG = constrain(analogValueG, minReadingGreen, maxReadingGreen); 130 | Serial.print(" Green = " ); 131 | Serial.println(analogValueG); 132 | analogOut = map(analogValueG, minReadingGreen, maxReadingGreen, 0, 255); 133 | analogOut = constrain(analogOut, 0, 255); 134 | Serial.print(" scaled to " ); 135 | Serial.println(analogOut, DEC); 136 | analogWrite(GreenPin, analogOut); 137 | 138 | //Blue 139 | analogValueB = analogRead(sensorPinBlue); 140 | analogValueB = constrain(analogValueB, minReadingBlue, maxReadingBlue); 141 | Serial.print(" Blue = " ); 142 | Serial.println(analogValueB); 143 | analogOut = map(analogValueB, minReadingBlue, maxReadingBlue, 0, 255); 144 | analogOut = constrain(analogOut, 0, 255); 145 | Serial.print(" scaled to " ); 146 | Serial.println(analogOut, DEC); 147 | analogWrite(BluePin, analogOut); 148 | 149 | delay (500); 150 | } 151 | -------------------------------------------------------------------------------- /VernierAnalogSensorThreshold/VernierAnalogSensorThreshold.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierAnalogSensorThreshold (v. 2018.05) 3 | Reads a Vernier analog (BTA) sensor connnected to pin A0 of the Arduino, Analog 1 on 4 | the Vernier Interface Shield. This sketch displays the sensor reading on the Serial Monitor. 5 | As written, the reading will be displayed every half second. Change the variable 6 | timeBetweenReadings to change the rate. 7 | 8 | This has code added to turn on line D13 if the sensor reading exceeds a 9 | threshold. 10 | 11 | See www.vernier.com/arduino for more information. 12 | 13 | */ 14 | #include "VernierLib.h" 15 | VernierLib Vernier; 16 | float sensorReading; 17 | int readingNumber; 18 | float threshold =100 ;// this is the limit you are setting (here we are using 100) 19 | //////////////////////////////////////// 20 | int timeBetweenReadings = 500; 21 | ///////////////////////////////////////// 22 | void setup() 23 | { 24 | Serial.begin(9600); //initialize serial communication at 9600 bits per second 25 | pinMode(13, OUTPUT); // This specifies that digital line D13 will be used for output (not input, which is the default) 26 | Vernier.autoID();// this is the routine to do the autoID Serial.println("Vernier Format 2"); 27 | Serial.println(Vernier.sensorName()); 28 | Serial.print(" "); 29 | Serial.println("Readings taken using Ardunio"); 30 | Serial.println("Data Set"); 31 | Serial.print("Time");//long name 32 | Serial.print("\t"); //tab character 33 | Serial.println(Vernier.sensorName()); 34 | Serial.print ("t"); //short name 35 | Serial.print("\t"); //tab character 36 | Serial.println(Vernier.shortName()); 37 | Serial.print("seconds");//units 38 | Serial.print("\t"); // tab character 39 | Serial.println(Vernier.sensorUnits()); 40 | } 41 | void loop() 42 | { 43 | sensorReading =Vernier.readSensor(); 44 | Serial.print(readingNumber/1000.0*timeBetweenReadings); 45 | Serial.print ("\t"); 46 | Serial.println(sensorReading); 47 | 48 | delay(timeBetweenReadings);// delay in between reads for stability 49 | if (sensorReading>threshold){ 50 | digitalWrite(13, HIGH); 51 | }// This turns on the LED 52 | else 53 | { 54 | digitalWrite(13,LOW); 55 | } 56 | readingNumber++; 57 | } 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /VernierBirthdayCandle/VernierBirthdayCandle.ino: -------------------------------------------------------------------------------- 1 | /* 2 | DCU-Controlled Birthday Candle (v 2016.05) 3 | Reads the temperature from a Vernier Surface Temperature Probe (STS-BTA) 4 | connected to the BTA 1 connector. As written, the readings will be displayed every half second. 5 | Change the variable TimeBetweenReadings to change the rate. 6 | 7 | We use the Steinhart-Hart equation (in the function Thermistor) to determine temperature 8 | from the raw A/D converter reading. Because of the use of log functions, in the Steinhart-Hart 9 | equation, this sketch requires the math.h library. 10 | 11 | This sketch controls a "fake birthday candle", which is really an LED connected to line 1 of the 12 | Digital Control Unit (DCU). 13 | 14 | Run the sketch and allow the temperature to stablize. When it has, press the D12 button on the Vernier 15 | Interface Shield. This will establish a threshold temperature. The candle should go out any time the 16 | temperature reading drops 2 degrees from this threshold temperture. 17 | 18 | See www.vernier.com/engineering/stem/sensors/temperature-sensor/ 19 | for more information on how thermistors are read. 20 | 21 | See www.vernier.com/arduino for more information. 22 | */ 23 | #include 24 | int ThermistorPIN =0;// Analog Pin 0 25 | int TimeBetweenReadings = 500; // in ms 26 | int ReadingNumber=0; 27 | int buttonPin= 12; // analog input pin to use as a digital input 28 | int LED= 13; // digital output pin for LED 1 indicator 29 | int Candle =6;// this is the line to control the candle if the using line 1 of the DCU in Digital 2 30 | float Threshold= 0; //Threshold temperature, initialize to 0 so candle is on 31 | int buttonState = 0;//variable for reading the pushbutton status 32 | void setup() 33 | { 34 | Serial.begin(9600); 35 | pinMode(LED, OUTPUT); //LED on SparkFun Vernier Shield 36 | pinMode(6, OUTPUT); // set Arduino line 6 for output, which is DCU line 1 (if DCU is connected to Digital 2) 37 | // Set up button input pin; 38 | pinMode(buttonPin, INPUT_PULLUP); 39 | Serial.println("Vernier Format 2"); 40 | Serial.println("Temperature Readings taken using Ardunio"); 41 | Serial.println("Data Set"); 42 | Serial.print("Time");//long name 43 | Serial.print("\t"); //tab character 44 | Serial.print ("Temperature"); 45 | Serial.print("\t"); //tab character 46 | Serial.println ("Threshold"); 47 | Serial.print("t"); 48 | Serial.print("\t"); //tab character 49 | Serial.println ("Temp"); //short name 50 | Serial.print("seconds"); 51 | Serial.print("\t"); // tab character 52 | Serial.print ("degrees C"); 53 | Serial.print("\t"); // tab character 54 | Serial.println ("degrees C"); 55 | } 56 | void loop() 57 | { 58 | float Time; 59 | int Count; //reading from the A/D converter (10-bit) 60 | float Temp; //the print below does the division first to avoid overflows 61 | Serial.print(ReadingNumber/1000.0*TimeBetweenReadings); 62 | Count=analogRead(ThermistorPIN); // read count from the A/D converter 63 | Temp=Thermistor(Count); // and convert it to CelsiusSerial.print(Time/1000); //display in seconds, not milliseconds 64 | Serial.print("\t"); //tab character 65 | Serial.print(Temp,1); // display temperature to one digit 66 | Serial.print("\t"); //tab character 67 | Serial.println (Threshold,1); 68 | if (Temp<(Threshold)) { 69 | digitalWrite(Candle, LOW); //turn off candle 70 | digitalWrite(LED, LOW); //turn off LED, also 71 | } 72 | else { 73 | digitalWrite (Candle, HIGH);//turn on candle 74 | digitalWrite(LED, HIGH); //turn on LED, also 75 | } 76 | //Special section to set threshold, if button is pressed: 77 | buttonState = digitalRead(buttonPin); 78 | // if it is, the buttonState is LOW: 79 | if (buttonState == LOW) 80 | { 81 | Threshold = Temp-2;// set this as the threshold temperature, 2 degrees C below current temp 82 | Serial.print("Threshold set as "); 83 | Serial.print (Threshold,1); 84 | Serial.println(" degrees C"); 85 | }// end of special operatures done if button is down 86 | 87 | ReadingNumber++; 88 | delay(TimeBetweenReadings); // Delay a bit... 89 | } 90 | 91 | float Thermistor(int Raw) //This function calculates temperature from ADC count 92 | { 93 | /* Inputs ADC count from Thermistor and outputs Temperature in Celsius 94 | * requires: include 95 | * There is a huge amount of information on the web about using thermistors with the Arduino. 96 | * Here we are concerned about using the Vernier Stainless Steel Temperature Probe TMP-BTA and the 97 | * Vernier Surface Temperature Probe STS-BTA, but the general principles are easy to extend to other 98 | * thermistors. 99 | * This version utilizes the Steinhart-Hart Thermistor Equation: 100 | * Temperature in Kelvin = 1 / {A + B[ln(R)] + C[ln(R)]^3} 101 | * for the themistor in the Vernier TMP-BTA probe: 102 | * A =0.00102119 , B = 0.000222468 and C = 1.33342E-7 103 | * Using these values should get agreement within 1 degree C to the same probe used with one 104 | * of the Vernier interfaces 105 | * 106 | * Schematic: 107 | * [Ground] -- [thermistor] -------- | -- [15,000 ohm resistor] --[Vcc (5v)] 108 | * | 109 | * Analog Pin 0 110 | For the circuit above: 111 | * Resistance = ( Count*RawADC /(1024-Count)) 112 | */ 113 | long Resistance; 114 | float Resistor = 15000; //fixed resistor 115 | // the measured resistance of your particular fixed resistor in 116 | // the Vernier BTA-ELV and in the SparkFun Vernier Adapter Shield 117 | // is a precision 15K resisitor 118 | float Temp; // Dual-Purpose variable to save space. 119 | Resistance=( Resistor*Raw /(1024-Raw)); 120 | Temp = log(Resistance); // Saving the Log(resistance) so not to calculate it 4 times later 121 | Temp = 1 / (0.00102119 + (0.000222468 * Temp) + (0.000000133342 * Temp * Temp * Temp)); 122 | Temp = Temp - 273.15; // Convert Kelvin to Celsius 123 | return Temp; // Return the Temperature 124 | } 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /VernierCount/VernierCount.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierCount (v 2017.07) 3 | Monitors a Vernier Drop Counter or Vernier photogate connected to BTD connector. 4 | 5 | The sketch sums the "Blocked" events in the period "countTime". As written, the 6 | countTime is 10 seconds. 7 | 8 | See www.vernier.com/arduino for more information. 9 | 10 | */ 11 | int photogate = 2; // Pin assignment for photogate 12 | int LEDpin = 13;/// line for LED to turn on when count is received. 13 | int countTime = 10000;// this is the total time between reported results, the collect time 14 | int intervalNumber =0; 15 | 16 | void setup() 17 | { 18 | Serial.begin(9600); // set up Serial library at 9600 bps 19 | pinMode(LEDpin, OUTPUT); 20 | Serial.println("Vernier Format 2"); 21 | Serial.println("Count Readings taken using Ardunio"); 22 | Serial.println("Data Set"); 23 | Serial.print("Int"); //long name 24 | Serial.print("\t"); //tab character 25 | Serial.println ("Count"); //long name 26 | Serial.print ("I"); //short name 27 | Serial.print("\t"); //tab character 28 | Serial.println("s"); //short name 29 | Serial.print("#"); //units 30 | Serial.print("\t"); // tab character 31 | Serial.println ("#"); //units 32 | };// end of setup 33 | 34 | void loop () 35 | { 36 | unsigned long timemsStart; 37 | int countSum = 0; 38 | 39 | timemsStart = millis(); 40 | while ((millis() - timemsStart) <= countTime) 41 | { 42 | if (digitalRead(photogate)==LOW) 43 | { 44 | digitalWrite(LEDpin, HIGH);// turn on LED 45 | countSum ++; 46 | while(digitalRead(photogate)==LOW); 47 | digitalWrite(LEDpin, LOW); //turn off LED 48 | } 49 | } 50 | Serial.print(intervalNumber); 51 | Serial.print("\t"); // tab character 52 | Serial.println(countSum); 53 | intervalNumber++; 54 | } ;// end of loop 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /VernierDigitalAutoID/VernierDigitalAutoID.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierDigitalAutoID (v 2014.12) 3 | Reads the information to AutoID a Vernier BTD sensor with resistor ID. 4 | 5 | When used with the SparkFun Vernier Interface Shield, this program will AutoID 6 | two different sensors on BTD1 and BTD2. With homemade, breadboard 7 | connections, it will work with only one sensor. 8 | 9 | After the AutoID, assuming Vernier analog (BTD) Sensors are connected to the BTD connectors, 10 | this sketch displays the name of the sensor and the units. This sketch does not read data 11 | because there are several different types of readings that can be done with digital sensors 12 | (distance measurements, radiation counts, photogate timing, etc). Instead, this sketch 13 | will name the Vernier Arduino sketch to use to read that sensor. For example, if you connect 14 | a Motion Detector, it will suggest the VernierMotionDetector program. 15 | 16 | See www.vernier.com/arduino for more information. 17 | */ 18 | int ReadingNumber; 19 | int Channel; //BTA (Channel 1 or 2) or BTD connector (Channel 3 or 4) 20 | float VoltageID[5]; 21 | int led =13; 22 | int SensorNumber[5]; //integer indicating sensor number' 23 | String Name[5]; 24 | String ShortName[5]; 25 | String Units[5]; 26 | float Intercept[5]; 27 | float Slope[5]; 28 | int Page[5]; 29 | int (CalEquationType[5]); 30 | float VCC= 5.00;// "5 volt" power supply voltage used in resistor ID section 31 | void setup() 32 | { 33 | int muxlsb = 10; //low byte of multiplexer 34 | int muxmsb = 11; //high byte of multiplexer 35 | Serial.begin(9600); 36 | pinMode(led, OUTPUT); //LED on SparkFun Vernier Shield 37 | digitalWrite(led, LOW); 38 | pinMode(muxlsb, OUTPUT); 39 | pinMode(muxmsb, OUTPUT); 40 | Serial.println(""); 41 | //Read BTD1 Sensor: 42 | digitalWrite(muxlsb, LOW); //set multiplexer for BTD1 43 | digitalWrite(muxmsb, HIGH); 44 | Channel=3; 45 | BTDResistorSensorID(Channel); 46 | PrintSensorInfo();// this line can be commented out if you do not need all this info !!! 47 | //Read BTD2 Sensor 48 | digitalWrite(muxlsb, HIGH); //set multiplexer for BTD2 49 | digitalWrite(muxmsb, HIGH); 50 | Channel=4; 51 | BTDResistorSensorID(Channel); 52 | PrintSensorInfo();// this line can be commented out if you do not need all this info !!! 53 | } 54 | 55 | void loop() 56 | { 57 | } 58 | 59 | void BTDResistorSensorID(int Channel) 60 | { 61 | Name[Channel]="";// clear name string 62 | ShortName[Channel]="";// clear name string 63 | SensorNumber[Channel] = 0; 64 | delay (10); 65 | int CountID = analogRead(A5); 66 | VoltageID[Channel] = CountID / 1023.0 * VCC;// convert from count to voltage 67 | if (VoltageID[Channel]>3.27 & VoltageID[Channel]<3.61) SensorNumber[Channel] = 2; //Motion Detector 68 | if (VoltageID[Channel]>4.45 & VoltageID[Channel]<4.46) SensorNumber[Channel] = 3; //motion not used 69 | if (VoltageID[Channel]>3.80 & VoltageID[Channel]<3.88) SensorNumber[Channel] = 4; //photogate 70 | if (VoltageID[Channel]>4.08 & VoltageID[Channel]<4.16) SensorNumber[Channel] = 5; //Drop Counter 71 | if (VoltageID[Channel]>4.32 & VoltageID[Channel]<4.40) SensorNumber[Channel] = 6; //rotary 72 | if (VoltageID[Channel]>4.50 & VoltageID[Channel]<4.59) SensorNumber[Channel] = 7;//Radiation Monitor 73 | if (VoltageID[Channel]>4.45 & VoltageID[Channel]<4.46) SensorNumber[Channel] = 8; //DCU - 1st generation 74 | if (VoltageID[Channel]>1.52 & VoltageID[Channel]<1.70) SensorNumber[Channel] = 9; //DCU - 2nd generation 75 | if (VoltageID[Channel]>1.18 & VoltageID[Channel]<1.30) SensorNumber[Channel] = 10; //Polarimeter 76 | if (VoltageID[Channel]>0.86 & VoltageID[Channel]<0.95) SensorNumber[Channel] = 11; //Projectile Launcher 77 | if (VoltageID[Channel]>0.62 & VoltageID[Channel]<0.68) SensorNumber[Channel] = 12; //Linear Translator for DAK 78 | if (VoltageID[Channel]>0.43 & VoltageID[Channel]<0.48) SensorNumber[Channel] = 13; //Motion Encoder 79 | if (VoltageID[Channel]>4.64 & VoltageID[Channel]<4.73) SensorNumber[Channel] = 14; // possible digital sensor 80 | switch (SensorNumber[Channel]) 81 | { 82 | case 2: 83 | Name[Channel] = "Motion - Position" ; 84 | Units[Channel] = "Use VernierMotionDetector" ; 85 | ShortName[Channel] = "Position"; 86 | Slope[Channel]=1; 87 | Intercept[Channel]=0; 88 | Page[Channel] = 1;; //calibration storage page 89 | CalEquationType[Channel]=1; 90 | break; 91 | case 3: 92 | Name[Channel] = "Motion -NU" ; 93 | Units[Channel] = "not used" ; 94 | ShortName[Channel] = "Motion -NU"; 95 | Slope[Channel]=1; 96 | Intercept[Channel]=0; 97 | Page[Channel] = 1;; //calibration storage page 98 | CalEquationType[Channel]=1; 99 | break; 100 | case 4: 101 | Name[Channel] = "Photogate" ; 102 | Units[Channel] = "Use VernierPhotogate" ; 103 | ShortName[Channel] = "PG"; 104 | Slope[Channel]=1; 105 | Intercept[Channel]=0; 106 | Page[Channel] = 1;; //calibration storage page 107 | CalEquationType[Channel]=1; 108 | break; 109 | case 5: 110 | Name[Channel] = "Drop Counter" ; 111 | Units[Channel] = "Use VernierCount" ; 112 | ShortName[Channel] = "Drop Count"; 113 | Slope[Channel]=1; 114 | Intercept[Channel]=0; 115 | Page[Channel] = 1;; //calibration storage page 116 | CalEquationType[Channel]=1; 117 | break; 118 | case 6: 119 | Name[Channel] = "Rotary Motion" ; 120 | Units[Channel] = "Use VernierRotary" ; 121 | ShortName[Channel] = "Rotary"; 122 | Slope[Channel]=1; 123 | Intercept[Channel]=0; 124 | Page[Channel] = 1;; //calibration storage page 125 | CalEquationType[Channel]=1; 126 | break; 127 | case 7: 128 | Name[Channel] = "Radiation Monitor" ; 129 | Units[Channel] = "Use Count" ; 130 | ShortName[Channel] = "VernierRadiation"; 131 | Slope[Channel]=1; 132 | Intercept[Channel]=0; 133 | Page[Channel] = 1;; //calibration storage page 134 | CalEquationType[Channel]=1; 135 | break; 136 | case 8: 137 | Name[Channel] = "DCU - 1st gen" ; 138 | Units[Channel] = "Use VernierDCU" ; 139 | ShortName[Channel] = "DCU -1"; 140 | Slope[Channel]=1; 141 | Intercept[Channel]=0; 142 | Page[Channel] = 1;; //calibration storage page 143 | CalEquationType[Channel]=1; 144 | break; 145 | case 9: 146 | Name[Channel] = "DCU - 2nd gen" ; 147 | Units[Channel] = "Use VernierDCU" ; 148 | ShortName[Channel] = "DCU-2"; 149 | Slope[Channel]=1; 150 | Intercept[Channel]=0; 151 | Page[Channel] = 1;; //calibration storage page 152 | CalEquationType[Channel]=1; 153 | break; 154 | case 10: 155 | Name[Channel] = "Polarimeter" ; 156 | Units[Channel] = "-----" ; 157 | ShortName[Channel] = "Polarimeter"; 158 | Slope[Channel]=1; 159 | Intercept[Channel]=0; 160 | Page[Channel] = 1;; //calibration storage page 161 | CalEquationType[Channel]=1; 162 | break; 163 | case 11: 164 | Name[Channel] = "Projectile Launcher" ; 165 | Units[Channel] = "Use VernierPhotogate" ; 166 | ShortName[Channel] = "Proj Time"; 167 | Slope[Channel]=1; 168 | Intercept[Channel]=0; 169 | Page[Channel] = 1;; //calibration storage page 170 | CalEquationType[Channel]=1; 171 | break; 172 | case 12: 173 | Name[Channel] = "DAK distance" ; 174 | Units[Channel] = "Use VernierRotary" ; 175 | ShortName[Channel] = "DAK d"; 176 | Slope[Channel]=1; 177 | Intercept[Channel]=0; 178 | Page[Channel] = 1;; //calibration storage page 179 | CalEquationType[Channel]=1; 180 | break; 181 | case 13: 182 | Name[Channel] = "Motion Encoder Dist" ; 183 | Units[Channel] = "Use VernierRotary" ; 184 | ShortName[Channel] = "ME Dist"; 185 | Slope[Channel]=1; 186 | Intercept[Channel]=0; 187 | Page[Channel] = 1;; //calibration storage page 188 | CalEquationType[Channel]=1; 189 | break; 190 | case 14: 191 | Name[Channel] = "Digital Sensor" ; 192 | Units[Channel] = "read digital ID" ; 193 | ShortName[Channel] = "D&"; 194 | Slope[Channel]=1; 195 | Intercept[Channel]=0; 196 | Page[Channel] = 1;; //calibration storage page 197 | CalEquationType[Channel]=1; 198 | break; 199 | default: 200 | Name[Channel] = "nothing on BTD" ; 201 | SensorNumber[Channel] = 0; // 202 | Units[Channel] = "" ; 203 | ShortName[Channel] = ""; 204 | Slope[Channel]=1; 205 | Intercept[Channel]=0; 206 | Page[Channel] = 1;; //calibration storage page 207 | CalEquationType[Channel]=1; 208 | break; 209 | } // end of switch case 210 | } // end of BTD resistor check 211 | 212 | 213 | void PrintSensorInfo() 214 | {// print out information about sensor 215 | Serial.println(" "); 216 | Serial.print("BTD connector "); 217 | Serial.println(Channel-2); 218 | Serial.print("sensor ID number: "); 219 | Serial.println(SensorNumber[Channel]); 220 | Serial.print("ID voltage level: "); 221 | Serial.println(VoltageID[Channel]); 222 | Serial.print("sensor name: "); 223 | Serial.println (Name[Channel]); 224 | Serial.print("sensor short name: "); 225 | Serial.println (ShortName[Channel]); 226 | Serial.print("calibration page: "); 227 | Serial.println(Page[Channel]); 228 | Serial.print("calibration equation type: "); 229 | Serial.println(CalEquationType[Channel]); 230 | Serial.print("intercept: "); 231 | Serial.println (Intercept[Channel]); 232 | Serial.print("slope "); 233 | Serial. println(Slope[Channel]); 234 | Serial.print("Program to use: "); 235 | Serial.println (Units[Channel]); 236 | }// end of PrintSensorInfo 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | -------------------------------------------------------------------------------- /VernierFreq_Motion/VernierFreq_Motion.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierFreq_Motion (v 2015.1) 3 | 4 | This sketch produces a tone on a speaker connected to pin D9 of 5 | the Arduino. The frequency of the tone will vary depending on how 6 | far from the motion detector (connected to Digital 1 of the Vernier 7 | Shield) an object is place. It was designed to be used as an 8 | audible aid for an Engineering Design Challenge at the Museum of 9 | Science (Boston). It is based on the Tone 2 tutorial. 10 | (see http://arduino.cc/en/Tutorial/Tone2). 11 | 12 | If you want to change the range of frequencies, change the last two 13 | numbers in the line: 14 | int thisPitch = map(sensorReading, 200, 15, 120, 1500) 15 | They are the minimum and maximum frequencies produced. 16 | If you want to change the sensitiviy of the system, change the first 17 | two numbers of the same line. They are the range of expected readings 18 | from the sensor. 19 | 20 | See www.vernier.com/arduino for details. 21 | */ 22 | int OutputPin=9; 23 | long time;// clock reading in microseconds 24 | long Duration; // time it take echo to return 25 | const int SpeedOfSound = 344; //in m/s 26 | double Distance;// in centimeters 27 | int val = 0; 28 | const int TriggerPin = 3; //trigger pin 29 | const int EchoPin = 2;// echo pin 30 | int Range=200; //distance in cm from Laser Pointer/Servo motor to Motion Detector 31 | void setup() 32 | { 33 | // initialize the Ping pin as an output: 34 | pinMode(TriggerPin, OUTPUT); 35 | pinMode(EchoPin, INPUT); //this is the pin that goes high when an echo is received 36 | // initialize serial communication at 9600 bits per second: 37 | Serial.begin(9600); 38 | Serial.println(" "); 39 | Serial.print("Distance"); 40 | Serial.print("Frequency"); 41 | Serial.println(" "); 42 | } 43 | 44 | void loop() { 45 | digitalWrite(TriggerPin, LOW); 46 | delayMicroseconds(4000); 47 | digitalWrite(TriggerPin, HIGH); // start the ultrasound pulse 48 | time = micros(); //note time 49 | delayMicroseconds(900); //delay during the blanking time 50 | do 51 | { 52 | val =digitalRead(EchoPin); 53 | // if no echo, repeat loop and wait: 54 | } 55 | while (val == LOW) ; 56 | Duration =micros() - time; 57 | /* The speed of sound is 344 m/s. 58 | The ultrasound travels out and back, so to find the distance of the 59 | object we take half of the distance traveled.*/ 60 | Distance= Duration *SpeedOfSound/2/10000 ;// note convert to cm 61 | Serial.println(Distance); 62 | 63 | delay(50); //delay a bit 64 | // read the sensor: 65 | float sensorReading = Distance; 66 | // print the sensor reading so you know its range 67 | 68 | /* map the distance input range (in this case, 200-15 (cm) from the motion detector) 69 | to the output pitch range (120 - 1500Hz). I wanted the pitch to increase with height 70 | and the Motion Detector sits atop the air tube, so the "measured distance" is relative 71 | to the top of the tube */ 72 | int thisPitch = map(sensorReading, 200, 15, 120, 1500); 73 | Serial.print(sensorReading); 74 | Serial.print ("/t"); 75 | Serial.print(thisPitch); 76 | // play the pitch: 77 | tone(OutputPin, thisPitch, 50); 78 | delay(50); // delay in between reads for stability 79 | } 80 | 81 | -------------------------------------------------------------------------------- /VernierFrequency/VernierFrequency.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierFrequency (v 2017.07) 3 | 4 | This sketch produces a tone on a speaker connected to pin D9 of 5 | the Arduino. It is based on the Tone 2 tutorial. 6 | (see http://arduino.cc/en/Tutorial/Tone2). 7 | 8 | Note that you do not deal with calibration here. Any Vernier 9 | Analog sensor which uses the Sig1 (0 to 5 volt) line will work 10 | if it is plugged into the BTA 1 connector. 11 | 12 | If you want to change the range of frequencies, change the last two 13 | numbers in the line: 14 | int thisPitch = map(sensorReading, 400, 1000, 120, 1500) 15 | They are the minimum and maximum frequencies produced. 16 | If you want to change the sensitiviy of the system, change the first 17 | two numbers of the same line. They are the range of expected readings 18 | from the sensor. 19 | 20 | See www.vernier.com/arduino for details. 21 | 22 | */ 23 | int outputPin=9; 24 | 25 | void setup() 26 | { 27 | // initialize serial communications (for debugging only): 28 | Serial.begin(9600); 29 | } 30 | 31 | void loop() { 32 | // read the sensor: 33 | int sensorReading = analogRead(A0); 34 | // print the sensor reading so you know its range 35 | Serial.println(sensorReading); 36 | // map the analog input range (in this case, 400 - 1000 from the photoresistor) 37 | // to the output pitch range (120 - 1500Hz) 38 | // change the minimum and maximum input numbers below 39 | // depending on the range your sensor's giving: 40 | int thisPitch = map(sensorReading, 400, 1000, 120, 1500); 41 | 42 | // play the pitch: 43 | tone(outputPin, thisPitch, 10); 44 | delay(1); // delay in between reads for stability 45 | } 46 | 47 | -------------------------------------------------------------------------------- /VernierHandControl1/VernierHandControl1.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierHandControl1(v 2018.05) 3 | 4 | This sketch was written to control one finger of the hand described in the Microsoft Hacking STEM hand project. 5 | 6 | This version reads a Vernier Low-G Accelerometers (LGA-BTA) sensors connected to the Analog 1 connnector of the Vernier 7 | Arduino Shield. It is read as pin A0 of the Arduino. 8 | 9 | This project requires the following hardware: 10 | - An Arduio Uno or Sparkfun Redboard 11 | - A Vernier Arduino Shield 12 | - a Vernier Digital Control Units (DCU-BTA) 13 | - a 6-volt power supplies such as Vernier LabPro power supplies or CBL2 Power supplies 14 | - tape for attaching the accelerometer to your finger 15 | 16 | The voltage is scaled using the handy Arduino Map function and then the servo motor is controlled. 17 | This version uses Analog 1 (Arduino line A0) to control just one fingers. 18 | There are more complex versions which requires more hardware. 19 | 20 | The servo motor ise assumed to be connected to the servo connector of the DCU in the Digital 2 connector of the shield. It is 21 | controlled by Arduino line D9. 22 | 23 | The DCU needs to be connected to 5- volt, LabQues power suppplY (LQ-PS) to supply the power for the servos. 24 | 25 | This version sets the finger to the up position at the start. 26 | It has you press the D12 button to get things started. This allows people to 27 | get the accelerometer in the up position before starting to move 28 | the servos. This will help avoid wild bending of the straw, which can damage them. 29 | */ 30 | 31 | #include 32 | //only two declared servos needed in this version. One is used for thumb and the other for all fingers 33 | Servo myservo0; // create servo object to control a servo for thumb 34 | 35 | int fingerStart= 580; //default LGA reading for starting (up) position of the finger 36 | int fingerStop= 450; //default LGA reading for down position of the finger 37 | int fingerSetting; 38 | int fingerSettingAverage=fingerStart ; 39 | //for button control: 40 | int buttonPin= 12; // analog input pin to use as a digital input 41 | int ledPin= 13; // digital output pin for LED 1 indicator 42 | int buttonVal = 0; // value read from button 43 | boolean buttonHasBeenPressed=LOW; 44 | 45 | void setup() 46 | { 47 | Serial.begin(9600); 48 | pinMode( 6, OUTPUT); 49 | pinMode( 7, OUTPUT); 50 | pinMode( 8, OUTPUT); 51 | pinMode( 9, OUTPUT); 52 | myservo0.attach(9);// attaches the servo object to a pin. This one uses the servo connector on DCU1, used for thumb 53 | 54 | digitalWrite(6, LOW); 55 | digitalWrite(7, LOW); 56 | digitalWrite(8, LOW);;//set unused DCU 2 lines low (to avoid problems caused by the DCU output patters for 13, 14, and 15 57 | 58 | // Set button input pin 59 | pinMode(buttonPin, INPUT);//pin 12 60 | digitalWrite(buttonPin, HIGH);//initialize button state 61 | pinMode(ledPin, OUTPUT);// Set LED output (pin 13) 62 | } 63 | 64 | void loop() 65 | { 66 | if (buttonHasBeenPressed == HIGH) //we have already dealt with the button 67 | { //This is the code to control the fingers 68 | fingerSetting= analogRead(0);// note channel A0 is for the finger 69 | 70 | float alpha= 0.7;//factor used in calculating a running averageing 71 | fingerSettingAverage=alpha*fingerSetting + (1-alpha)*fingerSettingAverage;// calculate running average 72 | 73 | Serial.println("Finger Setting: "); 74 | Serial.print(fingerSetting); 75 | Serial.print(" "); 76 | Serial.println(fingerSettingAverage); 77 | //delay (300);//slow down so you can read things 78 | 79 | setServos(); 80 | } // end of if 81 | 82 | else 83 | { //put hand in up position and read the state of the button 84 | fingerSetting= fingerStart; 85 | setServos(); //call subroutine to set servos. 86 | Serial.println("Press D12 button to start hand control. Finger is now up:"); 87 | delay (100); 88 | //now test for button press: 89 | buttonVal = digitalRead(buttonPin);// Test for button pressed, button down is low 90 | if (buttonVal== LOW) buttonHasBeenPressed = HIGH; //button pressed 91 | }//end of else 92 | } //end of loop 93 | 94 | void setServos()//set servo. This assumes that the fingerSetting[] 95 | { //is correct and used as a global variable. 96 | 97 | int servoSetting0;//used for finger position 98 | servoSetting0 = map(fingerSettingAverage,fingerStart, fingerStop, 11, 179);// scale it to match the index finger 99 | //the last two numbers in the statement above control the range of motion of the servo motor 100 | myservo0.write (servoSetting0);// set finger position 101 | 102 | /* //print these out if you want to see servo setting: 103 | Serial.println("ServoSetting: ");// print these out if you need to for testing. 104 | Serial.println(servoSetting0); 105 | delay (300); 106 | */ 107 | }// end of setServo subroutine 108 | 109 | 110 | -------------------------------------------------------------------------------- /VernierHandControl2/VernierHandControl2.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierHandControl2(v 2018.05) 3 | 4 | This sketch was written to control the hand described in the Microsoft Hacking STEM hand project. 5 | 6 | This version reads 2 Vernier Low-G Accelerometers (LGA-BTA) sensors connected to pins A0 and A2 of the Arduino. 7 | It requires the following hardware: 8 | - A Sparkfun Redboard or Arduio Uno 9 | - A Vernier Arduino Shield 10 | - (2) Vernier Digital Control Units (DCU-BTA) 11 | - (2) 5-volt power supplies such as Vernier LabQuest power supplies (Vernier order code LQ-PS) 12 | - a glove 13 | - tape, glue or some method of attaching the two accelerometers to the glove 14 | 15 | The voltage is scaled using the handy Arduino Map function and then the servo motors are controlled. 16 | This version uses Analog 1 (Arduino line A0) to control the thumb and Analog 2 (Arduino line A2) to control the 4 fingers. 17 | There is a more complex version which requires more hardware. That version is controlled with the VernierHandControl5 sketch. 18 | 19 | The five servo motors are assumed to be connected to pin D1, D2, D5, D6, and D9 of the Arduino as follows: 20 | - The thumb servo is controlled by the DCU in Digital 1, and uses the servo connector (Arduino line D5) 21 | - The thumb finger servo is controlled by the DCU in Digital 2, and uses the servo connector (Arduino line D9) 22 | - The smallest finger (pinky) servo is controlled by the DCU in Digital 1, and uses the servo connector (Arduino line D2) 23 | - The ring finger servo is controlled by the DCU in Digital 1, and uses the servo connector (Arduino line D3) 24 | - The middle servo is controlled by the DCU in Digital 2, and uses the screw terminal 1 connector (Arduino line D6) 25 | 26 | You may want to use short wires to make the connections between the screw terminals and the servo moter connetors. 27 | 28 | The DCUs are connected to two 5-volt, LabQuest power suppplies (Vernier order code LQ-PS) to supply the power for the servos. 29 | 30 | This version sets the fingers to the up position at the start. 31 | It has you press the D12 button to get things started. This allows people to 32 | get the controlling glove in the up position before starting to move 33 | the servos. This will help avoid wild bending of the straws, which can damage them. 34 | 35 | We have a more complex version of this project, which usese 2 Arduinos (with shields) and 4 accelerometers to give more 36 | complete control of the fingers. 37 | */ 38 | 39 | #include 40 | //only two declared servos needed in this version. One is used for thumb and the other for all fingers 41 | Servo myservo0; // create servo object to control a servo for thumb 42 | Servo myservo1; // create servo object to control a servo for all fingers 43 | Servo myservo2; // create servo object to control a servo for all fingers 44 | Servo myservo3; // create servo object to control a servo for all fingers 45 | Servo myservo4; // create servo object to control a servo for all fingers 46 | 47 | int finger; 48 | int thumbStart= 605; //default LGA reading for thumb in up position 49 | int fingerStart= 580; //default LGA reading for starting position of all fingers in the up position 50 | int thumbStop= 470; //default LGA reading for thumb in the down position 51 | int fingerStop= 450; //default LGA reading for all fingers in the down position 52 | int fingerSetting; 53 | int thumbSetting; 54 | int fingerSettingAverage=fingerStart ; 55 | int thumbSettingAverage= thumbStart; 56 | //for button control: 57 | int buttonPin= 12; // analog input pin to use as a digital input 58 | int ledPin= 13; // digital output pin for LED 1 indicator 59 | int buttonVal = 0; // value read from button 60 | boolean buttonHasBeenPressed=LOW; 61 | 62 | void setup() 63 | { 64 | Serial.begin(9600); 65 | pinMode( 2, OUTPUT);//set all DCU lines for output: 66 | pinMode( 3, OUTPUT); 67 | pinMode( 4, OUTPUT); 68 | pinMode( 5, OUTPUT); 69 | pinMode( 6, OUTPUT); 70 | pinMode( 7, OUTPUT); 71 | pinMode( 8, OUTPUT); 72 | pinMode( 9, OUTPUT); 73 | myservo0.attach(5);// attaches the servo object to a pin. This one uses the servo connector on DCU1, used for thumb 74 | myservo1.attach(9);// servo connector on DCU2, used for index finger 75 | myservo2.attach(2);// screw terminal 1 on DCU connected to Digital 1 , used for pinky) 76 | myservo3.attach(3);// screw terminal 2 on DCU connected to Digital 1 , used for ring finger) 77 | myservo4.attach(6);// screw terminal 1 on DCU connected to Digital 2 , used for middle finger) 78 | 79 | digitalWrite(4, LOW);//set unused DCU 1 lines low (to avoid problems caused by the DCU output patters for 13, 14, and 15 80 | digitalWrite(8, LOW);//set unused DCU 2 lines low (to avoid problems caused by the DCU output patters for 13, 14, and 15 81 | 82 | // Set button input pin 83 | pinMode(buttonPin, INPUT);//pin 12 84 | digitalWrite(buttonPin, HIGH);//initialize button state 85 | pinMode(ledPin, OUTPUT);// Set LED output (pin 13) 86 | 87 | } 88 | 89 | void loop() 90 | { 91 | if (buttonHasBeenPressed == HIGH) //we have already dealt with the button 92 | { //This is the code to control the fingers 93 | thumbSetting= analogRead(0);// note channel A0 is thumb 94 | fingerSetting= analogRead(2);// note channel A2 is for all fingers 95 | 96 | float alpha= 0.7;//factor used in calculating a running averageing 97 | thumbSettingAverage=alpha*thumbSetting + (1-alpha)*thumbSettingAverage;// calculate running average 98 | fingerSettingAverage=alpha*fingerSetting + (1-alpha)*fingerSettingAverage;// calculate running average 99 | 100 | Serial.println("thumb and Finger Settings: "); 101 | Serial.print(thumbSetting); 102 | Serial.print(" "); 103 | Serial.print(thumbSettingAverage); 104 | Serial.print(" "); 105 | Serial.print(fingerSetting); 106 | Serial.print(" "); 107 | Serial.println(fingerSettingAverage); 108 | //delay (300);//slow down so you can read things 109 | 110 | setServos(); 111 | } // end of if 112 | 113 | else 114 | { //put hand in up position and read the state of the button 115 | thumbSetting= thumbStart; 116 | fingerSetting= fingerStart; 117 | setServos(); //call subroutine to set servos. 118 | Serial.println("Press D12 button to start hand control. All fingers are now up:"); 119 | delay (100); 120 | //now test for button press: 121 | buttonVal = digitalRead(buttonPin);// Test for button pressed, button down is low 122 | if (buttonVal== LOW) buttonHasBeenPressed = HIGH; //button pressed 123 | }//end of else 124 | } //end of loop 125 | 126 | void setServos()//set servo. This assumes that the fingerSetting[] 127 | { //is correct and used as a global variable. 128 | 129 | int servoSetting0;//used for thumb finger 130 | int servoSetting1;//used for middle finger 131 | servoSetting0 = map(thumbSettingAverage,thumbStart, thumbStop, 11, 179);// scale it to match the thumb 132 | //the last two numbers in the statement above control the range of motion of the servo motor 133 | servoSetting1 = map(fingerSettingAverage,fingerStart, fingerStop, 11, 179);// scale it to match the fingers 134 | //the last two numbers in the statement above control the range of motion of the servo motor 135 | myservo0.write (servoSetting0);// set thumb position 136 | myservo1.write (servoSetting1); //set finger position 137 | myservo2.write (servoSetting1); //set finger position 138 | myservo3.write (servoSetting1); //set finger position 139 | myservo4.write (servoSetting1); //set finger position 140 | 141 | /* //print these out if you want to see servo settings: 142 | Serial.print("ServoSettings: ");// print these out if you need to for testing. 143 | Serial.print(servoSetting0); 144 | Serial.print (" "); 145 | Serial.println(servoSetting1); 146 | delay (300); 147 | */ 148 | }// end of setServo subroutine 149 | 150 | 151 | -------------------------------------------------------------------------------- /VernierHandControl4-1/VernierHandControl4-1.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierHandControl4-2(v 2018.05) 3 | 4 | This sketch was written to control the thumb. ring, and smallest finger of the hand described in the Microsoft Hacking STEM hand project. 5 | 6 | The DCUs are connected to two 5- volt, LabQuest power suppplies (Vernier order code LQ-PS) to supply the power for the servos. 7 | The system sometime does not not work well with a 5-volt power supply connected to the DCU. 8 | 9 | This version sets the fingers to the up position at the start. 10 | It has you press the D12 button to get things started. This allows people to 11 | get the controlling glove in the up position before starting to move 12 | the servos. This will help avoid wild bending of the straws, which can damage them. 13 | */ 14 | 15 | #include 16 | Servo myservo0; // create servo object to control a servo for thumb 17 | Servo myservo1; // create servo object to control a servo for smallest finger 18 | Servo myservo2; // create servo object to control a servo for ring finger 19 | int thumbStart= 605; //default LGA reading for thumb in up position 20 | int fingerStart= 580; //default LGA reading for starting position of ring and smallest fingers 21 | int thumbStop= 470; //default LGA reading for thumb in up position 22 | int fingerStop= 450; //default LGA reading for starting position of ring and smallest fingers 23 | int fingerSetting; 24 | int thumbSetting; 25 | int fingerSettingAverage=fingerStart; 26 | int thumbSettingAverage= thumbStart; 27 | //for button control: 28 | int buttonPin= 12; // analog input pin to use as a digital input 29 | int ledPin= 13; // digital output pin for LED 1 indicator 30 | int buttonVal = 0; // value read from button 31 | boolean buttonHasBeenPressed=LOW; 32 | 33 | void setup() 34 | { 35 | Serial.begin(9600); 36 | pinMode( 2, OUTPUT);//set all DCU lines for output: 37 | pinMode( 3, OUTPUT); 38 | pinMode( 4, OUTPUT); 39 | pinMode( 5, OUTPUT); 40 | pinMode( 6, OUTPUT); 41 | pinMode( 7, OUTPUT); 42 | pinMode( 8, OUTPUT); 43 | pinMode( 9, OUTPUT); 44 | myservo0.attach(5);// attaches the servo object to a pin. This one uses the servo connector on DCU1, used for thumb 45 | myservo1.attach(2);// servo connector on DCU2, used for smallest finger 46 | myservo2.attach(3);// screw terminal 1 on DCU connected to Digital 1 , used for ring finger 47 | digitalWrite(4, LOW);//set unused DCU 1 lines low (to avoid problems caused by the DCU output patters for 13, 14, and 15 48 | digitalWrite(8, LOW);//set unused DCU 2 lines low (to avoid problems caused by the DCU output patters for 13, 14, and 15 49 | 50 | // Set button input pin 51 | pinMode(buttonPin, INPUT);//pin 12 52 | digitalWrite(buttonPin, HIGH);//initialize button state 53 | pinMode(ledPin, OUTPUT);// Set LED output (pin 13) 54 | 55 | } 56 | 57 | void loop() 58 | { 59 | if (buttonHasBeenPressed == HIGH) //we have already dealt with the button 60 | { //This is the code to control the fingers 61 | thumbSetting= analogRead(0);// note channel A0 is for thumb 62 | fingerSetting= analogRead(2);// note channel A2 is for ring and smallest finger 63 | 64 | float alpha= 0.7;//factor used in calculating a running averageing 65 | thumbSettingAverage=alpha*thumbSetting + (1-alpha)*thumbSettingAverage;// calculate running average 66 | fingerSettingAverage=alpha*fingerSetting + (1-alpha)*fingerSettingAverage;// calculate running average 67 | 68 | Serial.println("Thumb and Finger Settings: "); 69 | Serial.print(thumbSetting); 70 | Serial.print(" "); 71 | Serial.print(thumbSettingAverage); 72 | Serial.print(" "); 73 | Serial.print(fingerSetting); 74 | Serial.print(" "); 75 | Serial.println(fingerSettingAverage); 76 | //delay (300);//slow down so you can read things 77 | 78 | setServos(); 79 | } // end of if 80 | 81 | else 82 | { //put hand in up position and read the state of the button 83 | thumbSetting= thumbStart; 84 | fingerSetting= fingerStart; 85 | setServos(); //call subroutine to set servos. 86 | Serial.println("Press D12 button to start hand control. All fingers are now up:"); 87 | delay (100); 88 | //now test for button press: 89 | buttonVal = digitalRead(buttonPin);// Test for button pressed, button down is low 90 | if (buttonVal== LOW) buttonHasBeenPressed = HIGH; //button pressed 91 | }//end of else 92 | } //end of loop 93 | 94 | void setServos()//set servo. This assumes that the fingerSetting[] 95 | { //is correct and used as a global variable. 96 | 97 | int servoSetting0;//used for thumb 98 | int servoSetting1;//used for middle and smallest fingers 99 | 100 | servoSetting0 = map(thumbSettingAverage,thumbStart, thumbStop, 11, 179);// scale it to match the thumb 101 | //the last two numbers in the statement above control the range of motion of the servo motor 102 | servoSetting1 = map(fingerSettingAverage,fingerStart, fingerStop, 11, 179);// scale it to match the fingers 103 | //the last two numbers in the statement above control the range of motion of the servo motor 104 | //servoSetting0 = map(thumbSetting,thumbStart, thumbStop, 11, 179); //thumb (Has its own control) 105 | // servoSetting1 = map(fingerSetting,fingerStart, fingerStop, 11, 179);// scale it to match the ring and smallest finger s 106 | myservo0.write (servoSetting0);// set thumb position 107 | myservo1.write (servoSetting1); //set smallest finger position 108 | myservo2.write (servoSetting1); //set ring finger position 109 | /* //print these out if you want to see servo settings: 110 | Serial.print("ServoSettings: ");// print these out if you need to for testing. 111 | Serial.print(servoSetting0); 112 | Serial.print (" "); 113 | Serial.println(servoSetting1); 114 | delay (300); 115 | */ 116 | }// end of setServo subroutine 117 | 118 | 119 | -------------------------------------------------------------------------------- /VernierHandControl4-2/VernierHandControl4-2.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierHandControl4-2(v 2018.05) 3 | 4 | This sketch was written to control the index and middle finger of the hand described in the Microsoft Hacking STEM hand project. 5 | 6 | The DCUs are connected to two 5- volt, LabQuest power suppplies (Vernier order code LQ-PS) to supply the power for the servos. 7 | 8 | This version sets the fingers to the up position at the start. 9 | It has you press the D12 button to get things started. This allows people to 10 | get the controlling glove in the up position before starting to move 11 | the servos. This will help avoid wild bending of the straws, which can damage them. 12 | */ 13 | 14 | #include 15 | //only two declared servos needed in this version. One is used for index and the other for middle finger 16 | Servo myservo0; // create servo object to control a servo for index finger 17 | Servo myservo1; // create servo object to control a servo for middle finger 18 | 19 | int finger; 20 | int indexStart= 540; //default LGA reading for index in up position 21 | int fingerStart= 570; //default LGA reading for starting position of ring fingers 22 | int indexStop= 470; //default LGA reading for thumb in up position 23 | int fingerStop= 450; //default LGA reading for starting position of ring and smallest fingers 24 | int fingerSetting; 25 | int indexSetting; 26 | int fingerSettingAverage=fingerStart ; 27 | int indexSettingAverage= indexStart; 28 | //for button control: 29 | int buttonPin= 12; // analog input pin to use as a digital input 30 | int ledPin= 13; // digital output pin for LED 1 indicator 31 | int buttonVal = 0; // value read from button 32 | boolean buttonHasBeenPressed=LOW; 33 | 34 | void setup() 35 | { 36 | Serial.begin(9600); 37 | pinMode( 2, OUTPUT);//set all DCU lines for output: 38 | pinMode( 3, OUTPUT); 39 | pinMode( 4, OUTPUT); 40 | pinMode( 5, OUTPUT); 41 | pinMode( 6, OUTPUT); 42 | pinMode( 7, OUTPUT); 43 | pinMode( 8, OUTPUT); 44 | pinMode( 9, OUTPUT); 45 | myservo0.attach(9);// attaches the servo object to a pin. This one uses the servo connector on DCU1, used for index 46 | myservo1.attach(6);// servo connector on DCU2, used for smallest finger 47 | digitalWrite(4, LOW);//set unused DCU 1 lines low (to avoid problems caused by the DCU output patters for 13, 14, and 15 48 | digitalWrite(8, LOW);//set unused DCU 2 lines low (to avoid problems caused by the DCU output patters for 13, 14, and 15 49 | 50 | // Set button input pin 51 | pinMode(buttonPin, INPUT);//pin 12 52 | digitalWrite(buttonPin, HIGH);//initialize button state 53 | pinMode(ledPin, OUTPUT);// Set LED output (pin 13) 54 | 55 | } 56 | 57 | void loop() 58 | { 59 | if (buttonHasBeenPressed == HIGH) //we have already dealt with the button 60 | { //This is the code to control the fingers 61 | indexSetting= analogRead(0);// note channel A0 is index finger 62 | fingerSetting= analogRead(2);// note channel A2 is for middle finger 63 | 64 | float alpha= 0.7;//factor used in calculating a running averageing 65 | indexSettingAverage=alpha*indexSetting + (1-alpha)*indexSettingAverage;// calculate running average 66 | fingerSettingAverage=alpha*fingerSetting + (1-alpha)*fingerSettingAverage;// calculate running average 67 | 68 | Serial.println("Index and Finger Settings: "); 69 | Serial.print(indexSetting); 70 | Serial.print(" "); 71 | Serial.print(indexSettingAverage); 72 | Serial.print(" "); 73 | Serial.print(fingerSetting); 74 | Serial.print(" "); 75 | Serial.println(fingerSettingAverage); 76 | //delay (300);//slow down so you can read things 77 | 78 | setServos(); 79 | } // end of if 80 | 81 | else 82 | { //put hand in up position and read the state of the button 83 | indexSetting= indexStart; 84 | fingerSetting= fingerStart; 85 | setServos(); //call subroutine to set servos. 86 | Serial.println("Press D12 button to start hand control. All fingers are now up:"); 87 | delay (100); 88 | //now test for button press: 89 | buttonVal = digitalRead(buttonPin);// Test for button pressed, button down is low 90 | if (buttonVal== LOW) buttonHasBeenPressed = HIGH; //button pressed 91 | }//end of else 92 | } //end of loop 93 | 94 | void setServos()//set servo. This assumes that the fingerSetting[] 95 | { //is correct and used as a global variable. 96 | 97 | int servoSetting0;//used for index finger 98 | int servoSetting1;//used for middle finger 99 | servoSetting0 = map(indexSettingAverage,indexStart, indexStop, 11, 179); //index (Has its own control) 100 | servoSetting1 = map(fingerSettingAverage,fingerStart, fingerStop, 11, 179);// scale it to match the index finger 101 | //servoSetting0 = map(indexSetting,indexStart, indexStop, 11, 179); //index (Has its own control) 102 | // servoSetting1 = map(fingerSetting,fingerStart, fingerStop, 11, 179);// scale it to match the middle finger 103 | myservo0.write (servoSetting0);// set index position 104 | myservo1.write (servoSetting1); //set middle finger position 105 | /* //print these out if you want to see servo settings: 106 | Serial.print("ServoSettings: ");// print these out if you need to for testing. 107 | Serial.print(servoSetting0); 108 | Serial.print (" "); 109 | Serial.println(servoSetting1); 110 | delay (300); 111 | */ 112 | }// end of setServo subroutine 113 | 114 | 115 | -------------------------------------------------------------------------------- /VernierISE/VernierISE.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierISE (v 2017.09) 3 | Read a Vernier analog (BTA) Ion Selective Electrode (ISE) sensor connected to Analog 1 4 | port of the Vernier Sensor. 5 | The ISE probes can be tricky to use with the Arduino because the sensor must be 6 | calibrated before each use and the probe response is not linear, but rather is 7 | modeled by the Nernst Equation. 8 | The Arduino provides a 10-bit readout (0-1023) from the electrode. The sketch 9 | uses the Vernier Library to read the sensor with units of mV using this standard calibration for the 10 | electrode. 11 | 12 | E = 137.55*Voltage -0.1682. (units of mV) 13 | 14 | In order to determine the concentration in mg/l the mV response must be entered into 15 | the Nernst equation: 16 | 17 | E = Eo + m(ln C) 18 | 19 | The trick with these probes and the Nernst equation is that the sensor membrane changes with 20 | time. It is likely that each time you go to use the sensor it will have changed 21 | enough to require a new calibration. 22 | 23 | If this is important to your application, determine the values of Eo and m by using 2 known 24 | concentration solutions and measure the corresponding Eo. You can only expect these values 25 | to remain valid for a short period of time and then you will need to do this again. 26 | Enter these values in the sketch. 27 | 28 | This sketch displays the the electrode response (in mV), and the concentration (in mg/l) 29 | The concentration will be accurate only if the values of Eo and m are calibrated for the 30 | specific sensor you are using. As written, the reading will be displayed every half second 31 | on the serial monitor. Change the variable TimeBetweenReadings to change the rate. 32 | 33 | See www.vernier.com/arduino for more information. 34 | */ 35 | #include "VernierLib.h" 36 | VernierLib Vernier; 37 | float sensorReading; 38 | float Eo = 252.72; //Enter the values from your calibration here 39 | float m = -7.59; // Enter the values from your calibration here 40 | void setup() 41 | { 42 | Serial.begin(9600); 43 | Vernier.autoID();// this is the routine to do the autoID 44 | printSensorInfo(); 45 | } 46 | 47 | void loop() 48 | { 49 | sensorReading =Vernier.readSensor(); 50 | double(val) = ((sensorReading-Eo)/m); // calculates the value to be entered into exp func. 51 | float concentration = exp(val); // converts mV value to concentration 52 | Serial.print(sensorReading); 53 | Serial.print(" "); 54 | Serial.print(Vernier.sensorUnits()); 55 | Serial.print("\t"); 56 | Serial.print(concentration); 57 | Serial.println(" mg/l"); 58 | delay(500);//half a second 59 | } 60 | void printSensorInfo() 61 | { 62 | // print out information about the sensor found: 63 | Serial.println("Sensor Information:"); 64 | Serial.print("Sensor ID number: "); 65 | Serial.print("\t"); 66 | Serial.println(Vernier.sensorNumber()); 67 | Serial.print("Sensor Name: "); 68 | Serial.print("\t"); 69 | Serial.println(Vernier.sensorName()); 70 | Serial.print("Short Name: "); 71 | Serial.print("\t"); 72 | Serial.println(Vernier.shortName()); 73 | Serial.print("Units: "); 74 | Serial.print("\t"); 75 | Serial.println(Vernier.sensorUnits()); 76 | Serial.print("ID voltage level: "); 77 | Serial.print("\t"); 78 | Serial.println(Vernier.voltageID()); 79 | Serial.print("Page: "); 80 | Serial.print("\t"); 81 | Serial.println(Vernier.page()); 82 | Serial.print("slope: "); 83 | Serial.print("\t"); 84 | Serial.println(Vernier.slope()); 85 | Serial.print("intercept: "); 86 | Serial.print("\t"); 87 | Serial.println(Vernier.intercept()); 88 | Serial.print("cFactor:"); 89 | Serial.print("\t"); 90 | Serial.println(Vernier.cFactor()); 91 | Serial.print("calEquationType: "); 92 | Serial.print("\t"); 93 | Serial.println(Vernier.calEquationType()); 94 | } 95 | -------------------------------------------------------------------------------- /VernierLaserTracker/VernierLaserTracker.ino: -------------------------------------------------------------------------------- 1 | /*VernierLaserTracker (v 2018.5) 2 | Monitors the position of an object using a Vernier Motion Detector 3 | and then aims a laser pointer mounted on a servo motor at the object. 4 | 5 | This sketch uses three Arduino libraries. To read the Motion Detector, it uses 6 | the VernierLib library. Because of the use of a trig function (arctangent) in the 7 | calculations, this sketch requires the math.h library. It also requires the servo 8 | library to control the servo motor. 9 | 10 | See www.vernier.com/arduino for more information. 11 | */ 12 | #include 13 | #include 14 | Servo myservo; // create servo object to control a servo 15 | #include "VernierLib.h" 16 | VernierLib Vernier; 17 | float distance = 0;// distqnce in cm 18 | int Range=100; //distance in cm from Laser Pointer/Servo motor to Motion Detector 19 | const int Laser = 6;//laser pin, connect laser to pin 6 of the Arduino, which is the first line on Digital 2 20 | 21 | void setup() 22 | { 23 | myservo.attach(9); // attaches the servo on pin 9 to the servo object 24 | // initialize serial communication at 9600 bits per second: 25 | Serial.begin(9600); 26 | Serial.println(" "); 27 | Serial.print("Distance"); 28 | Serial.print("\t"); //tab character 29 | Serial.print ("Angle"); 30 | Serial.print("\t"); //tab character 31 | Serial.println ("Angle"); 32 | Serial.print("centimeters"); 33 | Serial.print("\t"); // tab character 34 | Serial.print ("radians"); 35 | Serial.print("\t"); // tab character 36 | Serial.println ("degrees"); 37 | } 38 | void loop() 39 | { 40 | float ArcTan=0; 41 | double Angle =0; 42 | float Degrees; 43 | int ServoSetting; 44 | distance = Vernier.readMotionDetector(); 45 | Serial.print(distance); 46 | Serial.println(" cm"); 47 | if (distance < 120) 48 | { 49 | digitalWrite(Laser, HIGH);// if closest item is within 120 cm it turns laser on 50 | } 51 | else digitalWrite(Laser, LOW); 52 | delay(100);//delay a tenth of a second 53 | 54 | Serial.print(distance); 55 | Serial.print("\t"); // tab character 56 | ArcTan = atan(distance/Range); 57 | Serial.print(ArcTan); 58 | Serial.print("\t"); // tab character 59 | Degrees= ArcTan*57.29578; //convert radians to degrees 60 | Serial.println(Degrees); 61 | ServoSetting =Degrees; 62 | myservo.write(ServoSetting); // sets the servo position according to the scaled value 63 | delay(50); //delay a bit 64 | } 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /VernierLaserTrackerAutoOn/VernierLaserTrackerAutoOn.ino: -------------------------------------------------------------------------------- 1 | /*VernierLaserTracker (v 2018.5) 2 | Monitors the position of an object using a Vernier Motion Detector 3 | and then aims a laser pointer mounted on a servo motor at the object. 4 | 5 | This sketch uses three Arduino libraries. To read the Motion Detector, it uses 6 | the VernierLib library. Because of the use of a trig function (arctangent) in the 7 | calculations, this sketch requires the math.h library. It also requires the servo 8 | library to control the servo motor. 9 | 10 | See www.vernier.com/arduino for more information. 11 | */ 12 | #include 13 | #include 14 | Servo myservo; // create servo object to control a servo 15 | #include "VernierLib.h" 16 | VernierLib Vernier; 17 | float distance = 0;// distqnce in cm 18 | int Range=100; //distance in cm from Laser Pointer/Servo motor to Motion Detector 19 | const int laser = 6;//laser pin, connect laser to pin 6 of the Arduino, which is the first line on Digital 2 20 | 21 | void setup() 22 | { 23 | myservo.attach(9); // attaches the servo on pin 9 to the servo object 24 | // initialize serial communication at 9600 bits per second: 25 | Serial.begin(9600); 26 | Serial.println(" "); 27 | Serial.print("Distance"); 28 | Serial.print("\t"); //tab character 29 | Serial.print ("Angle"); 30 | Serial.print("\t"); //tab character 31 | Serial.println ("Angle"); 32 | Serial.print("centimeters"); 33 | Serial.print("\t"); // tab character 34 | Serial.print ("radians"); 35 | Serial.print("\t"); // tab character 36 | Serial.println ("degrees"); 37 | } 38 | void loop() 39 | { 40 | float ArcTan=0; 41 | double Angle =0; 42 | float Degrees; 43 | int ServoSetting; 44 | distance = Vernier.readMotionDetector(); 45 | Serial.print(distance); 46 | Serial.println(" cm"); 47 | if (distance < 120) 48 | { 49 | digitalWrite(laser, HIGH);// if closest item is within 120 cm it turns laser on 50 | } 51 | else digitalWrite(laser, LOW); 52 | delay(100);//delay a tenth of a second 53 | 54 | Serial.print(distance); 55 | Serial.print("\t"); // tab character 56 | ArcTan = atan(distance/Range); 57 | Serial.print(ArcTan); 58 | Serial.print("\t"); // tab character 59 | Degrees= ArcTan*57.29578; //convert radians to degrees 60 | Serial.println(Degrees); 61 | ServoSetting =Degrees; 62 | myservo.write(ServoSetting); // sets the servo position according to the scaled value 63 | delay(50); //delay a bit 64 | } 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /VernierLibDemo/VernierLibDemo.ino: -------------------------------------------------------------------------------- 1 | #include "VernierLib.h" 2 | VernierLib Vernier; 3 | float sensorReading; 4 | void setup() 5 | { 6 | Serial.begin(9600); 7 | Vernier.autoID();// this is the routine to do the autoID 8 | printSensorInfo(); 9 | } 10 | 11 | void loop() 12 | { 13 | sensorReading =Vernier.readSensor(); 14 | Serial.print(sensorReading); 15 | Serial.print(" "); 16 | Serial.println(Vernier.sensorUnits()); 17 | delay(500);//half a second 18 | } 19 | 20 | void printSensorInfo() 21 | { 22 | // print out information about the sensor found: 23 | Serial.println("Sensor Information:"); 24 | Serial.print("Sensor ID number: "); 25 | Serial.print("\t"); 26 | Serial.println(Vernier.sensorNumber()); 27 | Serial.print("Sensor Name: "); 28 | Serial.print("\t"); 29 | Serial.println(Vernier.sensorName()); 30 | Serial.print("Short Name: "); 31 | Serial.print("\t"); 32 | Serial.println(Vernier.shortName()); 33 | Serial.print("Units: "); 34 | Serial.print("\t"); 35 | Serial.println(Vernier.sensorUnits()); 36 | Serial.print("ID voltage level: "); 37 | Serial.print("\t"); 38 | Serial.println(Vernier.voltageID()); 39 | Serial.print("Page: "); 40 | Serial.print("\t"); 41 | Serial.println(Vernier.page()); 42 | Serial.print("slope: "); 43 | Serial.print("\t"); 44 | Serial.println(Vernier.slope()); 45 | Serial.print("intercept: "); 46 | Serial.print("\t"); 47 | Serial.println(Vernier.intercept()); 48 | Serial.print("cFactor:"); 49 | Serial.print("\t"); 50 | Serial.println(Vernier.cFactor()); 51 | Serial.print("calEquationType: "); 52 | Serial.print("\t"); 53 | Serial.println(Vernier.calEquationType()); 54 | } 55 | -------------------------------------------------------------------------------- /VernierLibDemoDCU/VernierLibDemoDCU.ino: -------------------------------------------------------------------------------- 1 | #include "VernierLib.h" 2 | VernierLib Vernier; 3 | byte DCUSetting= 0; 4 | float sensorReading; 5 | float threshold = 5.0; 6 | 7 | void setup() 8 | { 9 | Serial.begin(9600); 10 | Vernier.autoID();// this is the routine to do the autoID 11 | } 12 | void loop() 13 | { 14 | sensorReading = Vernier.readSensor(); 15 | Serial.print(sensorReading); 16 | Serial.print(" "); 17 | Serial.println(Vernier.sensorUnits()); 18 | if (sensorReading >threshold ) 19 | { 20 | DCUSetting =7; 21 | } 22 | else 23 | { 24 | DCUSetting =0; 25 | } 26 | Vernier.DCU(DCUSetting); 27 | delay(500); 28 | } 29 | -------------------------------------------------------------------------------- /VernierLibDemoMotionDetector/VernierLibDemoMotionDetector.ino: -------------------------------------------------------------------------------- 1 | #include "VernierLib.h" 2 | VernierLib Vernier; 3 | float distance = 0;// distqnce in cm 4 | void setup() 5 | { 6 | Serial.begin(9600); 7 | Serial.print("Motion Detector reading..."); 8 | } 9 | 10 | void loop() 11 | { 12 | distance = Vernier.readMotionDetector(); 13 | Serial.print(distance); 14 | Serial.println(" cm"); 15 | delay(100);//delay a tenth of a second 16 | } 17 | -------------------------------------------------------------------------------- /VernierMotionDetector/VernierMotionDetector.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierMotionDetector (v 2014.09) 3 | Takes data from a Vernier Motion Detector connected to BTD connector. 4 | 5 | This sketch measures the time taken for the ultrasound to return (in microseconds) 6 | and then calculates the corresponding distance (based on the speed of ultrasound 7 | in air) and displays the distance (in cm) on the Serial Monitor. 8 | 9 | Here is how the Vernier Motion Detector works: 10 | - when pin 2 on BTD is pulled high, this triggers the ultrasound pulse 11 | - the program then starts timing but then delays 0.9 ms *(blanking time, 12 | 0.9 seconds is the time it takes ultrasound to travel 15 cm twice (round trip)) 13 | - the program then monitors pin 1 on the BTD, waiting for it to go high. 14 | This happens when an echo is detected. 15 | 16 | As written, the reading will be displayed roughly every quarter of a second. 17 | Change the delay at the end of the loop to change the rate. 18 | 19 | See www.vernier.com/arduino for more information. 20 | */ 21 | const int TriggerPin = 3; //trigger pin 22 | const int EchoPin = 2;// echo pin 23 | 24 | void setup() 25 | { 26 | // initialize the Ping pin as an output: 27 | pinMode(TriggerPin, OUTPUT); 28 | pinMode(EchoPin, INPUT); //this is the pin that goes high when an echo is received 29 | // initialize serial communication at 9600 bits per second: 30 | Serial.begin(9600); 31 | Serial.println("Vernier Format 2"); 32 | Serial.println("Motion Detector Readings taken using Ardunio"); 33 | Serial.println("Data Set"); 34 | Serial.print("Time for Echo");//long name 35 | Serial.print("\t"); //tab character 36 | Serial.println ("Distance"); //long name 37 | Serial.print("delta t");//short name 38 | Serial.print("\t"); //tab character 39 | Serial.println ("D"); //short name 40 | Serial.print("seconds");//units 41 | Serial.print("\t"); // tab character 42 | Serial.println ("centimeters"); //units 43 | } 44 | void loop() 45 | { 46 | long time; // clock reading in microseconds 47 | long Duration; // time it take echo to return 48 | const float SpeedOfSound = 340; //in m/s 49 | float Distance;// in centimeters 50 | int val = 0; 51 | digitalWrite(TriggerPin, LOW); 52 | delayMicroseconds(4000); 53 | digitalWrite(TriggerPin, HIGH); // start the ultrasound pulse 54 | time = micros(); //note time 55 | delayMicroseconds(900); //delay during the blanking time 56 | do 57 | { 58 | val =digitalRead(EchoPin); 59 | // if no echo, repeat loop and wait: 60 | } 61 | while (val == LOW) ; 62 | Duration =micros() - time; 63 | /* The speed of sound is 340 m/s. 64 | The ultrasound travels out and back, so to find the distance of the 65 | object we take half of the distance traveled.*/ 66 | Distance= Duration *SpeedOfSound/2/10000 ;// note convert to cm 67 | Serial.print(Duration);// print the time it took until the echo 68 | Serial.print("\t"); // tab character 69 | Serial.println(Distance); 70 | delay(250); //delay a quarter of a second 71 | } 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /VernierMotionDetectorThreshold/VernierMotionDetectorThreshold.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierMotionDetectorThreshhold (v 2014.09) 3 | Takes data from a Vernier Motion Detector connected to BTD 1 connector. 4 | 5 | This sketch measures the time taken for the ultrasound to return (in microseconds) 6 | and then calculates the corresponding distance (based on the speed of ultrasound 7 | in air) and displays the distance (in cm) on the Serial Monitor. 8 | 9 | Here is how the Vernier Motion Detector works: 10 | - when pin 2 on BTD is pulled high the ultrasound pulse is triggered 11 | - the program then starts timing but then delays 0.9 ms *(blanking time, 12 | 0.9 seconds is the time it takes ultrasound to travel 15 cm twice (round trip)) 13 | - the program then monitors pin 1 on the BTD, waiting for it to go high. 14 | This happens when an echo is detected. 15 | 16 | As written, the reading will be displayed roughly every quarter of a second. 17 | Change the delay at the end of the loop to change the rate. 18 | 19 | This version turns on an LED connected to pin 13 if the distance is less 20 | than one meter. 21 | 22 | See www.vernier.com/arduino for more information. 23 | */ 24 | const int TriggerPin = 3; //trigger pin 25 | const int EchoPin = 2;// echo pin 26 | const int LedPin = 13;// LED pin 27 | 28 | void setup() 29 | { 30 | // initialize the Ping pin as an output: 31 | pinMode(TriggerPin, OUTPUT); 32 | pinMode(EchoPin, INPUT); //this is the pin that goes high when an echo is received 33 | pinMode(LedPin, OUTPUT); //used for the LED 34 | // initialize serial communication at 9600 bits per second: 35 | Serial.begin(9600); 36 | Serial.println("Vernier Format 2"); 37 | Serial.println("Motion Detector Readings taken using Ardunio"); 38 | Serial.println("Data Set"); 39 | Serial.print("Time for Echo");//long name 40 | Serial.print("\t"); //tab character 41 | Serial.println ("Distance"); //long name 42 | Serial.print("delta t");//short name 43 | Serial.print("\t"); //tab character 44 | Serial.println ("D"); //short name 45 | Serial.print("seconds");//units 46 | Serial.print("\t"); // tab character 47 | Serial.println ("meters"); //units 48 | } 49 | void loop() 50 | { 51 | long time;// clock reading in microseconds 52 | long Duration; // time it take echo to return 53 | const float SpeedOfSound = 340; //in m/s 54 | float Distance;// in centimeters 55 | int val = 0;digitalWrite(LedPin, LOW); 56 | digitalWrite(TriggerPin, LOW); 57 | delayMicroseconds(4000); 58 | digitalWrite(TriggerPin, HIGH); // start the ultrasound pulse 59 | time = micros(); //note time 60 | delayMicroseconds(900); //delay during the blanking time 61 | do 62 | { 63 | val =digitalRead(EchoPin); 64 | // if no echo, repeat loop and wait 65 | } 66 | while (val == LOW) ; 67 | Duration =micros() - time; 68 | /* The speed of sound is 340 m/s. 69 | The ultrasound travels out and back, so to find the distance of the 70 | object we take half of the distance traveled.*/ 71 | Distance= Duration *SpeedOfSound/2/10000 ;// note convert to cm 72 | Serial.print(Duration);// print the time it took until the echo 73 | Serial.print("\t"); // tab character 74 | Serial.println(Distance); 75 | if (Distance < 100) 76 | { 77 | // if distance< 1 meter 78 | digitalWrite(LedPin, HIGH); 79 | Serial.print(" *******"); 80 | } 81 | delay(250); //delay a quarter of a second 82 | } 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /VernierMousetrap/VernierMousetrap.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierMousetrap (v 2017.07) 3 | 4 | A Vernier Photogate should also be connnected to the second BTD 1 connector. 5 | The sketch monitors this photogate and Controls a stepper motor (unipolar or 6 | bipolar) via a Vernier Digital Control Unit (DCU) connected to the BTD 2 7 | connector. 8 | 9 | This sketch will continuously check the photogate and start the stepper 10 | motor rotating when the photogate is blocked. External power must be supplied 11 | to the DCU to drive the stepper motor. 12 | 13 | This version uses the VernierLib library 14 | 15 | See www.vernier.com/arduino for more information. 16 | */ 17 | 18 | #include "VernierLib.h" 19 | VernierLib Vernier; 20 | int photogateStatus = HIGH; 21 | int stepDelay = 30; //step time in ms 22 | int stepCount = 55; //number of stepCount to take 23 | int stepDirection = 0; //stepDirection 0 =CW 24 | int photogate = 2; //This is the input for a photogate on the BTD 1 connector 25 | int LEDpin = 13; /// line for LED to turn on when photogate is blocked 26 | 27 | void setup() 28 | { 29 | Serial.begin(9600); // set up Serial library at 9600 bps 30 | }// end of setup 31 | 32 | void loop () 33 | { 34 | Serial.println(" starting loop, waiting for mouse... "); 35 | photogateStatus = digitalRead(photogate);//low when blocked 36 | if (photogateStatus == LOW) 37 | { 38 | digitalWrite(LEDpin, HIGH);// turn on LED 39 | Serial.print(photogateStatus); 40 | Serial.println(" Blocked "); 41 | Vernier.DCUstep(stepCount,stepDirection, stepDelay);// use stepper motor to lower door 42 | Vernier.DCU(0);//Turn off all lines 43 | delay (10000); //wait 10 seconds, note that the Arduino/shield LED will stay on 44 | digitalWrite(LEDpin, LOW);// turn off Arduino/shield LED when ready to trap again 45 | } 46 | else 47 | { 48 | Vernier.DCU(0);//Turn off all lines 49 | digitalWrite(LEDpin, LOW);// turn off LED 50 | } 51 | } ;// end of loop 52 | 53 | 54 | -------------------------------------------------------------------------------- /VernierPendulumDriver/VernierPendulumDriver.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierPendulumDriver (v 2017.07) 3 | This sketch assumes that a Vernier Photogate is connected to BTD 1 and a 4 | Vernier Digital Control Unit (DCU) is connected to BTD2. 5 | 6 | The sketch is designed to drive a pendulum with a magnetic bob to 7 | keep it swinging "forever". When the pendulum passes through the Photogate, it 8 | triggers a short digital output from the DCU to an electromagnet. The 9 | electromagnet should be situated just below the low point of the pendulum bob's 10 | swing. The photogate should be situated so that the bob goes through it as it 11 | moves downward. The electromagnet will go on to pull the bob downward to add 12 | energy to the pendulumn system. 13 | 14 | The sketch also flashes an LED connected to D13 when the photogate is blocked, 15 | and notes the times at which the pendulum blocks the photogate. 16 | 17 | Start the sketch and then start the pendulum swinging with the bob going 18 | through the photogate before it reaches the bottom of the swing. 19 | 20 | See www.vernier.com/arduino for more information. 21 | 22 | */ 23 | #include "VernierLib.h" 24 | VernierLib Vernier; 25 | unsigned long timems = 0; //Time in ms 26 | unsigned long previousTime= 0;// remember the previous time 27 | int photogatePin =2; // 28 | int photogate = HIGH;// not blocked is HIGH 29 | int previousPhotogate=HIGH; 30 | 31 | int count=1; //used to determine which direction the pendulum is swinging 32 | int LEDpin =13;/// line for LED to turn on when photogate is blocked 33 | int DCUline = 6;//This line will turn on the first line of the DCU, if 34 | // the DCU is connected to BTD2 35 | void setup() 36 | { 37 | Serial.begin(9600); // set up Serial library at 9600 bps 38 | pinMode (photogatePin,INPUT); 39 | pinMode(DCUline, OUTPUT); 40 | pinMode(LEDpin, OUTPUT); 41 | Serial.println("Vernier Format 2"); 42 | Serial.println("Photogate periods taken using Ardunio"); 43 | Serial.print("Swing"); 44 | Serial.print("\t"); //tab character 45 | Serial.println ("Time"); //change to match sensor 46 | Serial.print("#"); 47 | Serial.print("\t"); // tab character 48 | Serial.println ("milliseconds"); 49 | };// end of setup 50 | 51 | void loop () 52 | { 53 | photogate = digitalRead(photogatePin);//low when blocked 54 | if (photogate == LOW) //low when blocked 55 | { 56 | digitalWrite(LEDpin, HIGH); 57 | if (previousPhotogate == HIGH) // if the photogate has just gone to the blocked state 58 | { 59 | count++; //increment count of times photogate has been blocked 60 | if (count % 2 == 0)// if the bob is moving in the right direction 61 | { 62 | timems = millis() ; 63 | Vernier.DCU(DCUline); // turn on DCU line 1 and the electromagnet DCU line 64 | // and print out the swing number and period 65 | Serial.print(count); 66 | Serial.print("\t"); // tab character 67 | Serial.println(timems-previousTime); 68 | previousTime= timems; // remember the previous time 69 | }// end of the section for action take at the end of the complete swing 70 | } // end of photogate just gone blocked section 71 | }// end of if photogate blocked 72 | else //photogate not blocked: 73 | { 74 | Vernier.DCU(0);// turn off DCU line 1 and the electromagnet 75 | digitalWrite(LEDpin, LOW);// turn off LED 76 | } 77 | previousPhotogate = photogate; 78 | } ;// end of loop 79 | 80 | 81 | -------------------------------------------------------------------------------- /VernierPhotogate/VernierPhotogate.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierPhotogate (v 2017.07) 3 | Monitors a Vernier Photogate connected to BTD 1 connector. 4 | 5 | This sketch lists the time that the photogate is blocked in 6 | microseconds and milliseconds since the program started running. 7 | 8 | The reason for the two time units is that the microsecond counter overflow 9 | fairly frequently. Use whichever time you like in your versions of this. 10 | 11 | See www.vernier.com/arduino for more information. 12 | 13 | */ 14 | unsigned long timems = 0; //Time in ms 15 | unsigned long timeus = 0; //Time in us 16 | int photogatePin =2; // 17 | int photogate = HIGH; 18 | int status; 19 | int LEDpin =13;/// line for LED to turn on when photogate is blocked 20 | 21 | void setup() 22 | { 23 | Serial.begin(9600); // set up Serial library at 9600 bps 24 | pinMode(LEDpin, OUTPUT); 25 | Serial.println("Vernier Format 2"); 26 | Serial.println("Photogate blocked times taken using Ardunio"); 27 | Serial.print("Time"); 28 | Serial.print("\t"); //tab character 29 | Serial.println ("Time"); //change to match sensor 30 | Serial.print("ms"); 31 | Serial.print("\t"); // tab character 32 | Serial.println ("microseconds"); 33 | };// end of setup 34 | 35 | void loop () 36 | { 37 | photogate = digitalRead(photogatePin);//low when blocked 38 | if (photogate == LOW) 39 | { 40 | digitalWrite(LEDpin, HIGH);// turn on LED 41 | if (status == HIGH) 42 | { 43 | timems = millis() ; 44 | timeus = micros() ; 45 | Serial.print(timems); 46 | Serial.print("\t"); //tab character 47 | Serial.println(timeus); 48 | } 49 | } 50 | else digitalWrite(LEDpin, LOW);// turn off LED 51 | status = photogate; 52 | } ;// end of loop 53 | 54 | 55 | -------------------------------------------------------------------------------- /VernierPingPongPID/VernierPingPongPID.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierMotionDetectorPID (v 2017.08) 3 | Takes data from a Vernier Motion Detector connected to Digital 1 connector. 4 | Uses PID to control fan to elevate ping pong ball to target height. The ball is in 5 | plastic tube 0.6 m tall with a fan at the bottom and a motion detector at the top. 6 | This version uses a Digital Control Unit (DCU) connected to the Digital 2 port to 7 | control the fan. 8 | 9 | Motion detector is read using the Vernier Library that calculates the distance based 10 | the echo of an ultrasonic sound wave. 11 | 12 | The PID control is modified from http://playground.arduino.cc/Code/PIDLibaryBasicExample 13 | and takes the calculated input from the motion detector ("distance") and controls analog PWM 14 | output 6 through the DCU (line 1).You will need to download the PID library from 15 | http://playground.arduino.cc/Code/PIDLibrary. 16 | 17 | As written, the reading will feed to the PID control continuously and data fed to 18 | Serial Print. 19 | 20 | There are several ways you can modify this. We have previously linked the output 21 | of this program to VPython to create a virtual display of the ping pong ball. 22 | Search the internet for tips on combining Arduino and VPython. You can also vary 23 | set point so that it seeks a variety of heights - definitely more eye catching. 24 | 25 | See www.vernier.com/arduino for more information. 26 | */ 27 | 28 | #include 29 | #include "VernierLib.h" 30 | VernierLib Vernier; 31 | double setPoint, distance, output; //define variables we'll be connecting to 32 | PID myPID(&distance, &output, &setPoint, 3,6.0,6.0, REVERSE); 33 | /*Specify the links and initial tuning parameters. These work for a system 34 | with a 0.6 m tube and the particular fan we are using. Depends on power supply 35 | to the fan as well as cowling around fan.*/ 36 | 37 | void setup() 38 | { 39 | Serial.begin(9600); 40 | 41 | setPoint = 40; // setpoint (cm from top) 42 | myPID.SetMode(AUTOMATIC); //turn the PID on 43 | 44 | Serial.println("Vernier Format 2"); 45 | Serial.println("Motion Detector Readings taken using Ardunio"); 46 | Serial.println("Data Set"); 47 | 48 | Serial.print("Set Point"); 49 | Serial.print("\t"); // tab character 50 | Serial.print ("Distance"); //long name 51 | Serial.print("\t"); 52 | Serial.println ("Output from PID"); 53 | 54 | Serial.print("SP (cm)"); 55 | Serial.print("\t"); 56 | Serial.print("\t"); 57 | Serial.print ("d (cm)"); //short name 58 | Serial.print("\t"); 59 | Serial.print("\t"); 60 | Serial.println("0 - 255"); 61 | } 62 | void loop() 63 | { 64 | distance = Vernier.readMotionDetector(); 65 | myPID.Compute(); 66 | analogWrite(6,output); 67 | Serial.print(setPoint); 68 | Serial.print("\t"); 69 | Serial.print("\t"); 70 | Serial.print(distance); 71 | Serial.print("\t"); 72 | Serial.print("\t"); 73 | Serial.println(output); 74 | delay (10); 75 | } 76 | -------------------------------------------------------------------------------- /VernierRadiation/VernierRadiation.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierRadiation (v 2014.12) 3 | Monitors a Vernier Radiation Monitor connected to BTD1 connector. 4 | 5 | The sketch sums the Radiation Monitor Counts in the period "CountTime". 6 | The default CountTime is 1 second. 7 | 8 | See www.vernier.com/arduino for more information. 9 | */ 10 | unsigned long TimeMsStart = 0; 11 | int rad = 2; // Pin assignment for radiation monitor 12 | int LEDpin =13;/// line for LED to turn on when count is received. 13 | int CountTime = 1000;// this is the total time between reported results 14 | int IntervalNumber =0;// tracks how many 1 second intervals 15 | 16 | void setup() 17 | { 18 | Serial.begin(9600); // set up Serial library at 9600 bps 19 | pinMode(LEDpin, OUTPUT); 20 | Serial.println("Vernier Format 2"); 21 | Serial.println("Radiation Count Readings taken using Ardunio"); 22 | Serial.println("Data Set"); 23 | Serial.print("Int");//long name 24 | Serial.print("\t"); //tab character 25 | Serial.println ("Count"); //long name 26 | Serial.print("I");//short name 27 | Serial.print("\t"); //tab character 28 | Serial.println ("C"); //short name 29 | Serial.print("#"); 30 | Serial.print("\t"); // tab character 31 | Serial.println ("#"); 32 | };// end of setup 33 | 34 | void loop () 35 | { 36 | int countSum = 0; 37 | 38 | TimeMsStart = millis(); 39 | while ((millis() - TimeMsStart) <= CountTime)// for 1 second 40 | { 41 | if (digitalRead(rad)==HIGH) 42 | { 43 | digitalWrite(LEDpin, HIGH);// turn on LED 44 | countSum ++;// adds a count 45 | digitalWrite(LEDpin, LOW); //turn off LED so it has to be forced back on 46 | } 47 | } 48 | Serial.print(IntervalNumber); 49 | Serial.print("\t"); // tab character 50 | Serial.println(countSum); 51 | IntervalNumber++; 52 | } ;// end of loop 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /VernierRotary/VernierRotary.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierRotary (v 2017.07) 3 | 4 | This sketch read a Vernier Rotary Motion Sensor connected to the BTD 1 connector. 5 | This sketch uses interrupts. It is very difficult to read the pulses from 6 | the Rotary Motion Sensor without interrupts. 7 | 8 | As written, the readings will be displayed every half second. Change the variable 9 | TimeBetweenReadings to change the rate. 10 | 11 | See www.vernier.com/arduino for details. 12 | 13 | */ 14 | const int encoderPinCCW = 2;// this assumes you are using the BTD 1 connector 15 | const int encoderPinCW = 3; 16 | const int XR = 5; // this pin controls the resolution of the Rotary Motion Sensor 17 | boolean highResOn = false;// this controls whether you are measuring in 18 | //high-res mode, to the nearest 1/4 degree. If not, it is to the nearest degree 19 | float res; //angle change for each transition (1 or 0.25 degrees) 20 | int readingNumber=0; 21 | volatile int encoderPos = 0; // variables changed within interrupts are volatile 22 | 23 | void setup() 24 | { 25 | pinMode(encoderPinCCW, INPUT); 26 | pinMode(encoderPinCW, INPUT); 27 | pinMode (XR, OUTPUT); 28 | digitalWrite(XR,highResOn); 29 | digitalWrite(encoderPinCCW, HIGH); 30 | digitalWrite(encoderPinCW, HIGH); 31 | Serial.begin(9600); 32 | attachInterrupt(0, doEncoderCCW, RISING); // encoder pin on interrupt 0 (pin 2) 33 | attachInterrupt(1, doEncoderCW, FALLING); // encoder pin on interrupt 1 (pin 3) 34 | if(highResOn) res = 0.25; 35 | else res =1; 36 | Serial.println("Vernier Format 2"); 37 | Serial.println("Rotary Motion Readings taken using Ardunio"); 38 | Serial.println("Data Set"); 39 | Serial.print("Time");//long name 40 | Serial.print("\t"); //tab character 41 | Serial.println ("Angle"); //long name 42 | Serial.print("t");//short name 43 | Serial.print("\t"); //tab character 44 | Serial.println ("A"); //short name 45 | Serial.print("seconds"); 46 | Serial.print("\t"); // tab character 47 | Serial.println ("degrees"); 48 | } 49 | 50 | void loop() 51 | { 52 | float readingTime; 53 | float pos, oldPos; 54 | int timeBetweenReadings = 500; // in ms 55 | uint8_t oldSREG = SREG; 56 | cli(); 57 | pos = encoderPos*res; 58 | SREG = oldSREG; 59 | readingTime = (readingNumber/1000.0*timeBetweenReadings); 60 | Serial.print(readingTime); // print time in seconds 61 | Serial.print("\t"); //tab character 62 | Serial.println(encoderPos*res); // display angle in degrees 63 | delay(timeBetweenReadings); // Delay a bit... 64 | readingNumber++; 65 | } 66 | 67 | void doEncoderCCW() 68 | { 69 | encoderPos++; // count UP 70 | } 71 | void doEncoderCW() 72 | { 73 | encoderPos--; // count DOWN 74 | } 75 | 76 | -------------------------------------------------------------------------------- /VernierServo/VernierServo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierServo (v 2015.04) 3 | Reads a Vernier analog (BTA) sensor connected to pin A0 of the Arduino or the 4 | BTA 1 connector. This sketch controls the arm on a servo motor in response to 5 | this voltage from the sensor. The servo motor is assumed to be connected to 6 | pin D9 of the Arduino. You can also connect to this line using the BTD 2 connector. 7 | This is an exception to our convention of reserving the BTD 2 connector for the 8 | digital readout. The servo motors must be controlled by pin 9 on the RedBoard/Arduino. 9 | 10 | This sketch is a very slight modification of the Knob sketch included with the 11 | Arduino 1.0.4 Examples. 12 | 13 | Note that if you have wired the BTD2 connector as we recommend on 14 | www.vernier.com/arduino or if you are using a SparkFun Vernier Interface Shield, 15 | you can make the connection to proper line for the servo motor from DIO4 (pin 9) of the 16 | BTD2 connector (the pin closest to the tab). 17 | 18 | If you connect the servo motor (3-pin) connector on a DCU and connect the DCU to 19 | the BTD2 connector on the Arduino Interface Shield, this (2015.04) version will work. 20 | The DCU will require an external power supply as the power received from the Redboard/ 21 | Arduino is not sufficient to drive the servo. 22 | 23 | */ 24 | 25 | #include 26 | Servo myservo; // create servo object to control a servo 27 | int Sensorpin = 0; // analog pin used to connect the potentiomete 28 | 29 | 30 | void setup() 31 | { 32 | myservo.attach(9); // attaches the servo on pin 9 to the servo object 33 | 34 | /* the 6 lines below are only needed if you plan to use this sketch with a servo motor 35 | connected to the 3-pin connector on a DCU. The reason this is required is that the DCU 36 | has internal electronics to only allow its 4th pin to be turned on when the other first 37 | three lines are off. 38 | */ 39 | 40 | pinMode(6, OUTPUT); 41 | pinMode(7, OUTPUT); 42 | pinMode(8, OUTPUT); 43 | pinMode(9, OUTPUT); 44 | digitalWrite(6, LOW); 45 | digitalWrite(7, LOW); 46 | digitalWrite(8, LOW); 47 | } 48 | void loop() 49 | { 50 | int val = analogRead(Sensorpin); // reads the voltage (value between 0 and 1023) 51 | val = map(val, 0, 1023, 0, 179); // scale it to use it with the servo (value between 0 and 180) 52 | myservo.write(val); // sets the servo position according to the scaled value 53 | delay(15); // waits for the servo to get there 54 | } 55 | -------------------------------------------------------------------------------- /VernierThermistor/VernierThermistor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierThermistor (v 2017.07) 3 | Reads the temperature from a Vernier Stainless Steel Temperature Probe (TMP-BTA) 4 | or Surface Temperature Sensor (STS-BTA) connected to the BTA 1 connector. 5 | As written, the readings will be displayed every half second. Change the variable 6 | TimeBetweenReadings to change the rate. 7 | 8 | We use the Steinhart-Hart equation (in the function Thermistor) to determine temperature 9 | from the raw A/D converter reading. Because of the use of log functions, in the Steinhart-Hart 10 | equation, this sketch requires the math.h library. 11 | 12 | See www.vernier.com/engineering/stem/sensors/temperature-sensor/ 13 | for more information on how thermistors are read. 14 | 15 | See www.vernier.com/arduino for more information. 16 | */ 17 | #include 18 | int thermistorPIN =0;// Analog Pin 0 19 | int timeBetweenReadings = 500; // in ms 20 | int readingNumber=0; 21 | 22 | void setup() 23 | { 24 | Serial.begin(9600); 25 | Serial.println("Vernier Format 2"); 26 | Serial.println("Temperature Readings taken using Ardunio"); 27 | Serial.println("Data Set"); 28 | Serial.print("Time");//long name 29 | Serial.print("\t"); //tab character 30 | Serial.println ("Temperature"); 31 | Serial.print("t"); 32 | Serial.print("\t"); //tab character 33 | Serial.println ("Temp"); //short name 34 | Serial.print("seconds"); 35 | Serial.print("\t"); // tab character 36 | Serial.println ("degrees C"); 37 | } 38 | void loop() 39 | { 40 | float readingTime; 41 | int count; //reading from the A/D converter (10-bit) 42 | float temp; //the print below does the division first to avoid overflows 43 | Serial.print(readingNumber/1000.0*timeBetweenReadings); 44 | count=analogRead(thermistorPIN); // read count from the A/D converter 45 | temp=thermistor(count); // and convert it to CelsiusSerial.print(Time/1000); //display in seconds, not milliseconds 46 | Serial.print("\t"); //tab character 47 | Serial.println(temp,1); // display temperature to one digit 48 | delay(timeBetweenReadings); // Delay a bit... 49 | readingNumber++; 50 | } 51 | 52 | float thermistor(int raw) //This function calculates temperature from ADC count 53 | { 54 | /* Inputs ADC count from Thermistor and outputs Temperature in Celsius 55 | * requires: include 56 | * There is a huge amount of information on the web about using thermistors with the Arduino. 57 | * Here we are concerned about using the Vernier Stainless Steel Temperature Probe TMP-BTA and the 58 | * Vernier Surface Temperature Probe STS-BTA, but the general principles are easy to extend to other 59 | * thermistors. 60 | * This version utilizes the Steinhart-Hart Thermistor Equation: 61 | * Temperature in Kelvin = 1 / {A + B[ln(R)] + C[ln(R)]^3} 62 | * for the themistor in the Vernier TMP-BTA probe: 63 | * A =0.00102119 , B = 0.000222468 and C = 1.33342E-7 64 | * Using these values should get agreement within 1 degree C to the same probe used with one 65 | * of the Vernier interfaces 66 | * 67 | * Schematic: 68 | * [Ground] -- [thermistor] -------- | -- [15,000 ohm resistor] --[Vcc (5v)] 69 | * | 70 | * Analog Pin 0 71 | For the circuit above: 72 | * Resistance = ( Count*RawADC /(1024-Count)) 73 | */ 74 | long resistance; 75 | float resistor = 15000; //fixed resistor 76 | // the measured resistance of your particular fixed resistor in 77 | // the Vernier BTA-ELV and in the SparkFun Vernier Adapter Shield 78 | // is a precision 15K resisitor 79 | float temp; // Dual-Purpose variable to save space. 80 | resistance=( resistor*raw /(1024-raw)); 81 | temp = log(resistance); // Saving the Log(resistance) so not to calculate it 4 times later 82 | temp = 1 / (0.00102119 + (0.000222468 * temp) + (0.000000133342 * temp * temp * temp)); 83 | temp = temp - 273.15; // Convert Kelvin to Celsius 84 | return temp; // Return the Temperature 85 | } 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /VernierThermistorDisplay/VernierThermistorDisplay.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierThermistorDisplay (v 2017.07) 3 | Reads the temperature from a Vernier Stainless Steel Temperature Probe (TMP-BTA) 4 | or Surface Temperature Sensor (STS-BTA) connected to the BTA connector. 5 | As written, the readings will be displayed every half second. Change the variable 6 | TimeBetweenReadings to change the rate. 7 | 8 | This version of the program uses the VernierLib library. 9 | 10 | See www.vernier.com/engineering/stem/sensors/temperature-sensor/ 11 | for more information on how thermistors are read. 12 | 13 | This sketch uses a 4-character, 7-Segment Serial Display to temperature 14 | readings in Celsius. The code for controlling the display was based on 15 | the Serial 7-Segment Display Example Code, Serial Mode Stopwatch by Jim Lindblom 16 | of SparkFun Electronics 17 | 18 | The print function is used with the SoftwareSerial library 19 | to send display data to the S7S. 20 | Here is the wiring for display with a UART serial connection: 21 | Arduino -------------- Serial 7-Segment 22 | 5V -------------------- VCC 23 | GND -------------------- GND 24 | 13 -------------------- RX 25 | */ 26 | #include "VernierLib.h" 27 | VernierLib Vernier; 28 | float sensorReading; 29 | #include 30 | // These are the Arduino pins required to create a software serial 31 | // instance. We'll actually only use the TX pin. 32 | const int softwareTx = 9; 33 | const int softwareRx = 7; 34 | SoftwareSerial s7s(softwareRx, softwareTx); 35 | char tempString[10]; // Will be used with sprintf to create strings 36 | int thermistorPIN =0;// Analog Pin 0 37 | float readingTime; 38 | int count; //reading from the A/D converter (10-bit) 39 | float temp; 40 | unsigned int temp100; 41 | int timeBetweenReadings = 500; // in ms 42 | int readingNumber=0; 43 | 44 | void setup() 45 | { 46 | Vernier.autoID();// this is the routine to do the autoID 47 | s7s.begin(9600); 48 | // Clear the display, and then turn on all segments and decimals 49 | clearDisplay(); // Clears display, resets cursor 50 | setDecimals(0b000000); // Turn on all decimals, colon, apos 51 | s7s.print("DEG."); // Displays Deg and then Cels on display 52 | delay (2000); 53 | s7s.print("CELS"); 54 | setBrightness(127); // Medium brightness 55 | delay(1500); 56 | setBrightness(255); // High brightness 57 | delay(1500); 58 | // Clear the display before jumping into loop 59 | clearDisplay(); 60 | } 61 | 62 | void loop() 63 | { 64 | sensorReading =Vernier.readSensor(); 65 | Serial.print(sensorReading); 66 | temp100 =sensorReading*100; 67 | // Magical sprintf creates a string for us to send to the s7s. 68 | // The %4d option creates a 4-digit integer. 69 | sprintf(tempString, "%4d", temp100); 70 | // This will output the tempString to the S7S 71 | s7s.print(tempString); 72 | setDecimals(0b0000010); // Sets digit 3 decimal on 73 | delay(timeBetweenReadings); // This will make the display update at about every half second 74 | } 75 | 76 | void clearDisplay() 77 | { 78 | s7s.write(0x76); // Clear display command 79 | } 80 | 81 | // Set the displays brightness. Should receive byte with the value 82 | // to set the brightness to 83 | // dimmest------------->brightest 84 | // 0--------127--------255 85 | 86 | void setBrightness(byte value) 87 | { 88 | s7s.write(0x7A); // Set brightness command byte 89 | s7s.write(value); // brightness data byte 90 | } 91 | 92 | // Turn on any, none, or all of the decimals. 93 | // The six lowest bits in the decimals parameter sets a decimal 94 | // (or colon, or apostrophe) on or off. A 1 indicates on, 0 off. 95 | // [MSB] (X)(X)(Apos)(Colon)(Digit 4)(Digit 3)(Digit2)(Digit1) 96 | void setDecimals(byte decimals) 97 | { 98 | s7s.write(0x77); 99 | s7s.write(decimals); 100 | } 101 | 102 | 103 | -------------------------------------------------------------------------------- /VernierThermistorStore/VernierThermistorStore.ino: -------------------------------------------------------------------------------- 1 | /* 2 | VernierThermistorStore (v 2014.06) 3 | Reads a Vernier Temperature Sensor (TMP-BTA or STS-BTA) connected to pin A0 4 | of the Arduino and and stores the data in the non-volatile EEPROM memory of the Arduino. 5 | This sketch displays the time and sensor readings on the Serial Monitor. 6 | As written, the readings will be displayed every minute. You can stop the 7 | data collection by pressing the button during data collection, after the 8 | first 3 points are taken. 9 | 10 | Change the variable TimeBetweenReadings to change the rate. 11 | Change the variable NumberOfReadings to change the number of data points to take. 12 | You can stop the data collection by pressing the button during data collection, 13 | after the first 3 points are taken. 14 | 15 | See www.vernier.com/arduino for more information, especially for information 16 | on how this sketch can be used to collect remote data with the Arduino away 17 | from a computer. 18 | 19 | Thanks to Brian Huang, for help on this program, especially the structure of a 20 | program to store and retrieve data. 21 | */ 22 | int buttonPin= 12; // analog input pin to use as a digital input 23 | int ledPin1= 13; // digital output pin for LED 1 indicator 24 | int debounce= 20; // ms debounce period to prevent flickering when pressing or releasing the button 25 | int holdTime= 2000; // ms hold period: how long to wait for press+hold event 26 | #include 27 | int base = 0; // the base address in EEPROM for data storage 28 | // note first two bytes store the number of points collected 29 | // Button variables 30 | int buttonVal = 0; // value read from button 31 | int buttonLast = 1; // buffered value of the button's previous state 32 | long btnDnTime; // time the button was pressed down 33 | long btnUpTime; // time the button was released 34 | long ReadingTime; //time at which a reading was taken 35 | long ElapsedTime; //time since last reading 36 | boolean ignoreUp = false; // whether to ignore the button release because the click+hold was triggered 37 | boolean ledVal1 = false; // state of LED 1 38 | int AnalogDataPin = A0; // this may be changed depending on circuit wiring 39 | int Count; 40 | float Voltage; 41 | float SensorReading; 42 | unsigned long Time; 43 | long unsigned int TimeBetweenReadings = 60000; //in ms, default is 1 minute 44 | int NumberOfPoints= 511; 45 | /////////////////////////////////// 46 | String SensorName = "Temperature"; 47 | String Measurement = "Temp"; 48 | String ShortMeasurement = "T"; // this is a shortened version of the label 49 | String Units = "Degrees C"; 50 | /////////////////////////////////// 51 | 52 | void setup() 53 | { 54 | // Set button input pin 55 | pinMode(buttonPin, INPUT); 56 | digitalWrite(buttonPin, HIGH); 57 | pinMode(AnalogDataPin, INPUT); 58 | pinMode(ledPin1, OUTPUT);// Set LED output pin 59 | Serial.begin(9600); 60 | Serial.println("VernierThermistorStore sketch"); 61 | Serial.println("Press and hold to collect new data"); 62 | Serial.println("Press button briefly to read data stored in EEPROM"); 63 | Serial.println("and send it to the Serial Monitor"); 64 | Serial.println(" "); 65 | } 66 | 67 | void loop() 68 | { 69 | digitalWrite(ledPin1, false); 70 | // Read the state of the button 71 | buttonVal = digitalRead(buttonPin);// button down is low 72 | // Test for button pressed and store the down time 73 | if (buttonVal == LOW && buttonLast == HIGH && (millis() - btnUpTime) > long(debounce)) 74 | { 75 | //button pressed 76 | btnDnTime = millis();// note time of press 77 | } 78 | // Test for button release and store the up time 79 | if (buttonVal == HIGH && buttonLast == LOW && (millis() - btnDnTime) > long(debounce)) 80 | { 81 | if (ignoreUp == false) ReadEEPROMData();// read data from EEPROM and send to Serial Monitor 82 | else ignoreUp = false; 83 | btnUpTime = millis();// note time of button release 84 | } 85 | // Test for button held down for longer than the hold time 86 | if (buttonVal == LOW && (millis() - btnDnTime) > long(holdTime)) 87 | { 88 | CollectData(); //collect new data 89 | ignoreUp = true; 90 | btnDnTime = millis(); // get new button down time 91 | } 92 | buttonLast = buttonVal; 93 | } 94 | //================================================= 95 | 96 | // Events to trigger by short click of button 97 | void ReadEEPROMData()// //Send data to Serial Monitor 98 | { 99 | ledVal1 = !ledVal1; 100 | digitalWrite(ledPin1, true); 101 | int NumberOfPointsRead;// local variable 102 | Serial.println("Send Data to Serial Monitor"); 103 | Serial.println(" "); 104 | int Sample = 0;// local variables 105 | int i = 0; 106 | int addr = base+ 2; //starting address of memory for data storage 107 | //note addr is laterincremented 108 | NumberOfPointsRead = EEPROM.read(base) + EEPROM.read(base+ 1)*256; 109 | Serial.println( "Vernier Format 2"); 110 | Serial.print(NumberOfPointsRead); 111 | Serial.print(" readings taken with a Vernier "); 112 | Serial.println(SensorName); 113 | Serial.println("Data Set From Arduino"); 114 | Serial.print("Time"); 115 | Serial.print("\t"); // print a tab character 116 | Serial.println(Measurement); 117 | Serial.print("T"); 118 | Serial.print("\t"); // print a tab character 119 | Serial.println(ShortMeasurement); 120 | Serial.print("s"); 121 | Serial.print("\t"); // print a tab character 122 | Serial.println(Units); 123 | for (i = 0; i <(NumberOfPointsRead)*2; i+=2) 124 | { 125 | Count = EEPROM.read(base+2 + i) | EEPROM.read(base+2 + i + 1) << 8; 126 | //the print below does the division first to avoid overflows 127 | Serial.print(i/2/1000.0*TimeBetweenReadings); 128 | Serial.print("\t"); // print a tab character 129 | SensorReading =Thermistor(Count); //This function calculates temperature from ADC count 130 | Serial.println(SensorReading); 131 | } 132 | Serial.println(" "); 133 | Serial.println("Press and hold button to collect new data "); 134 | Serial.println(" "); 135 | digitalWrite(ledPin1, false); //turn off LED 136 | //end of send data to Serial Monitor 137 | } 138 | 139 | //================================================= 140 | // Events to trigger by long click of button 141 | void CollectData() //Collect Data 142 | { 143 | ledVal1 = !ledVal1; 144 | Serial.begin(9600); 145 | Serial.println("Collecting Data..."); 146 | Serial.println(" "); 147 | int Sample = 0;// local variable 148 | int addr = base+ 2; //starting address of memory for data storage 149 | //note addr is later incremented 150 | Serial.println( "Vernier Format 2"); 151 | Serial.print("Data taken with a Vernier "); 152 | Serial.println(SensorName); 153 | Serial.println("Data Set From Arduino"); 154 | Serial.print("Reading"); 155 | Serial.print("\t"); 156 | Serial.print("Time"); 157 | Serial.print("\t"); // print a tab character 158 | Serial.println(Measurement); 159 | Serial.print("n"); 160 | Serial.print("\t"); 161 | Serial.print("T"); 162 | Serial.print("\t"); // print a tab character 163 | Serial.println(ShortMeasurement); 164 | Serial.print("#"); 165 | Serial.print("\t"); 166 | Serial.print("s"); // print a tab character 167 | Serial.print("\t"); 168 | Serial.println(Units); 169 | Sample=0; 170 | do 171 | { 172 | ReadingTime = millis();// note time of reading 173 | digitalWrite(ledPin1, true); 174 | Serial.print(Sample); 175 | Serial.print("\t"); 176 | //the print below does the division first to avoid overflows 177 | Serial.print(Sample/1000.0*TimeBetweenReadings); 178 | Serial.print("\t"); 179 | Count= analogRead(AnalogDataPin); 180 | SensorReading =Thermistor(Count); //This function calculates temperature from ADC count SensorReading =Thermistor(Count); //This function calculates temperature from ADC count 181 | Serial.println(SensorReading); 182 | EEPROM.write(addr, lowByte(Count)); 183 | EEPROM.write(addr + 1, highByte(Count)); 184 | addr +=2; //increment address pointer twice 185 | delay (300);//turn off LED after this time 186 | digitalWrite(ledPin1, false); 187 | do 188 | { 189 | buttonVal = digitalRead(buttonPin);// check button status 190 | ElapsedTime=millis()-ReadingTime; 191 | } 192 | while ((buttonVal==HIGH || Sample< 3) && (ElapsedTime 218 | * There is a huge amount of information on the web about using thermistors with the Arduino. 219 | * Here we are concerned about using the Vernier Stainless Steel Temperature Probe TMP-BTA and the 220 | * Vernier Surface Temperature Probe STS-BTA, but the general principles are easy to extend to other 221 | * thermistors. 222 | * This version utilizes the Steinhart-Hart Thermistor Equation: 223 | * Temperature in Kelvin = 1 / {A + B[ln(R)] + C[ln(R)]^3} 224 | * for the themistor in the Vernier TMP-BTA probe: 225 | * A =0.00102119 , B = 0.000222468 and C = 1.33342E-7 226 | * Using these values should get agreement within 1 degree C to the same probe used with one 227 | * of the Vernier interfaces 228 | * 229 | * Schematic: 230 | * [Ground] -- [thermistor] -------- | -- [15,000 ohm resistor] --[Vcc (5v)] 231 | * | 232 | * Analog Pin 0 233 | For the circuit above: 234 | * Resistance = ( Count*RawADC /(1024-Count)) 235 | */ 236 | long Resistance; 237 | float Resistor = 15000; //fixed resistor 238 | // the measured resistance of your particular fixed resistor in 239 | // the Vernier BTA-ELV and in the SparkFun Vernier Adapter Shield 240 | // is a precision 15K resisitor 241 | float Temp; // Dual-Purpose variable to save space. 242 | Resistance=( Resistor*Raw /(1024-Raw)); 243 | Temp = log(Resistance); // Saving the Log(resistance) so not to calculate it 4 times later 244 | Temp = 1 / (0.00102119 + (0.000222468 * Temp) + (0.000000133342 * Temp * Temp * Temp)); 245 | Temp = Temp - 273.15; // Convert Kelvin to Celsius 246 | return Temp; // Return the Temperature 247 | } 248 | -------------------------------------------------------------------------------- /libraries/PID/PID_v1.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * Arduino PID Library - Version 1.1.1 3 | * by Brett Beauregard brettbeauregard.com 4 | * 5 | * This Library is licensed under a GPLv3 License 6 | **********************************************************************************************/ 7 | 8 | #if ARDUINO >= 100 9 | #include "Arduino.h" 10 | #else 11 | #include "WProgram.h" 12 | #endif 13 | 14 | #include 15 | 16 | /*Constructor (...)********************************************************* 17 | * The parameters specified here are those for for which we can't set up 18 | * reliable defaults, so we need to have the user set them. 19 | ***************************************************************************/ 20 | PID::PID(double* Input, double* Output, double* Setpoint, 21 | double Kp, double Ki, double Kd, int POn, int ControllerDirection) 22 | { 23 | myOutput = Output; 24 | myInput = Input; 25 | mySetpoint = Setpoint; 26 | inAuto = false; 27 | 28 | PID::SetOutputLimits(0, 255); //default output limit corresponds to 29 | //the arduino pwm limits 30 | 31 | SampleTime = 100; //default Controller Sample Time is 0.1 seconds 32 | 33 | PID::SetControllerDirection(ControllerDirection); 34 | PID::SetTunings(Kp, Ki, Kd, POn); 35 | 36 | lastTime = millis()-SampleTime; 37 | } 38 | 39 | /*Constructor (...)********************************************************* 40 | * To allow backwards compatability for v1.1, or for people that just want 41 | * to use Proportional on Error without explicitly saying so 42 | ***************************************************************************/ 43 | 44 | PID::PID(double* Input, double* Output, double* Setpoint, 45 | double Kp, double Ki, double Kd, int ControllerDirection) 46 | :PID::PID(Input, Output, Setpoint, Kp, Ki, Kd, P_ON_E, ControllerDirection) 47 | { 48 | 49 | } 50 | 51 | 52 | /* Compute() ********************************************************************** 53 | * This, as they say, is where the magic happens. this function should be called 54 | * every time "void loop()" executes. the function will decide for itself whether a new 55 | * pid Output needs to be computed. returns true when the output is computed, 56 | * false when nothing has been done. 57 | **********************************************************************************/ 58 | bool PID::Compute() 59 | { 60 | if(!inAuto) return false; 61 | unsigned long now = millis(); 62 | unsigned long timeChange = (now - lastTime); 63 | if(timeChange>=SampleTime) 64 | { 65 | /*Compute all the working error variables*/ 66 | double input = *myInput; 67 | double error = *mySetpoint - input; 68 | double dInput = (input - lastInput); 69 | outputSum+= (ki * error); 70 | 71 | /*Add Proportional on Measurement, if P_ON_M is specified*/ 72 | if(!pOnE) outputSum-= kp * dInput; 73 | 74 | if(outputSum > outMax) outputSum= outMax; 75 | else if(outputSum < outMin) outputSum= outMin; 76 | 77 | /*Add Proportional on Error, if P_ON_E is specified*/ 78 | double output; 79 | if(pOnE) output = kp * error; 80 | else output = 0; 81 | 82 | /*Compute Rest of PID Output*/ 83 | output += outputSum - kd * dInput; 84 | 85 | if(output > outMax) output = outMax; 86 | else if(output < outMin) output = outMin; 87 | *myOutput = output; 88 | 89 | /*Remember some variables for next time*/ 90 | lastInput = input; 91 | lastTime = now; 92 | return true; 93 | } 94 | else return false; 95 | } 96 | 97 | /* SetTunings(...)************************************************************* 98 | * This function allows the controller's dynamic performance to be adjusted. 99 | * it's called automatically from the constructor, but tunings can also 100 | * be adjusted on the fly during normal operation 101 | ******************************************************************************/ 102 | void PID::SetTunings(double Kp, double Ki, double Kd, int POn) 103 | { 104 | if (Kp<0 || Ki<0 || Kd<0) return; 105 | 106 | pOn = POn; 107 | pOnE = POn == P_ON_E; 108 | 109 | dispKp = Kp; dispKi = Ki; dispKd = Kd; 110 | 111 | double SampleTimeInSec = ((double)SampleTime)/1000; 112 | kp = Kp; 113 | ki = Ki * SampleTimeInSec; 114 | kd = Kd / SampleTimeInSec; 115 | 116 | if(controllerDirection ==REVERSE) 117 | { 118 | kp = (0 - kp); 119 | ki = (0 - ki); 120 | kd = (0 - kd); 121 | } 122 | } 123 | 124 | /* SetTunings(...)************************************************************* 125 | * Set Tunings using the last-rembered POn setting 126 | ******************************************************************************/ 127 | void PID::SetTunings(double Kp, double Ki, double Kd){ 128 | SetTunings(Kp, Ki, Kd, pOn); 129 | } 130 | 131 | /* SetSampleTime(...) ********************************************************* 132 | * sets the period, in Milliseconds, at which the calculation is performed 133 | ******************************************************************************/ 134 | void PID::SetSampleTime(int NewSampleTime) 135 | { 136 | if (NewSampleTime > 0) 137 | { 138 | double ratio = (double)NewSampleTime 139 | / (double)SampleTime; 140 | ki *= ratio; 141 | kd /= ratio; 142 | SampleTime = (unsigned long)NewSampleTime; 143 | } 144 | } 145 | 146 | /* SetOutputLimits(...)**************************************************** 147 | * This function will be used far more often than SetInputLimits. while 148 | * the input to the controller will generally be in the 0-1023 range (which is 149 | * the default already,) the output will be a little different. maybe they'll 150 | * be doing a time window and will need 0-8000 or something. or maybe they'll 151 | * want to clamp it from 0-125. who knows. at any rate, that can all be done 152 | * here. 153 | **************************************************************************/ 154 | void PID::SetOutputLimits(double Min, double Max) 155 | { 156 | if(Min >= Max) return; 157 | outMin = Min; 158 | outMax = Max; 159 | 160 | if(inAuto) 161 | { 162 | if(*myOutput > outMax) *myOutput = outMax; 163 | else if(*myOutput < outMin) *myOutput = outMin; 164 | 165 | if(outputSum > outMax) outputSum= outMax; 166 | else if(outputSum < outMin) outputSum= outMin; 167 | } 168 | } 169 | 170 | /* SetMode(...)**************************************************************** 171 | * Allows the controller Mode to be set to manual (0) or Automatic (non-zero) 172 | * when the transition from manual to auto occurs, the controller is 173 | * automatically initialized 174 | ******************************************************************************/ 175 | void PID::SetMode(int Mode) 176 | { 177 | bool newAuto = (Mode == AUTOMATIC); 178 | if(newAuto && !inAuto) 179 | { /*we just went from manual to auto*/ 180 | PID::Initialize(); 181 | } 182 | inAuto = newAuto; 183 | } 184 | 185 | /* Initialize()**************************************************************** 186 | * does all the things that need to happen to ensure a bumpless transfer 187 | * from manual to automatic mode. 188 | ******************************************************************************/ 189 | void PID::Initialize() 190 | { 191 | outputSum = *myOutput; 192 | lastInput = *myInput; 193 | if(outputSum > outMax) outputSum = outMax; 194 | else if(outputSum < outMin) outputSum = outMin; 195 | } 196 | 197 | /* SetControllerDirection(...)************************************************* 198 | * The PID will either be connected to a DIRECT acting process (+Output leads 199 | * to +Input) or a REVERSE acting process(+Output leads to -Input.) we need to 200 | * know which one, because otherwise we may increase the output when we should 201 | * be decreasing. This is called from the constructor. 202 | ******************************************************************************/ 203 | void PID::SetControllerDirection(int Direction) 204 | { 205 | if(inAuto && Direction !=controllerDirection) 206 | { 207 | kp = (0 - kp); 208 | ki = (0 - ki); 209 | kd = (0 - kd); 210 | } 211 | controllerDirection = Direction; 212 | } 213 | 214 | /* Status Funcions************************************************************* 215 | * Just because you set the Kp=-1 doesn't mean it actually happened. these 216 | * functions query the internal state of the PID. they're here for display 217 | * purposes. this are the functions the PID Front-end uses for example 218 | ******************************************************************************/ 219 | double PID::GetKp(){ return dispKp; } 220 | double PID::GetKi(){ return dispKi;} 221 | double PID::GetKd(){ return dispKd;} 222 | int PID::GetMode(){ return inAuto ? AUTOMATIC : MANUAL;} 223 | int PID::GetDirection(){ return controllerDirection;} 224 | 225 | -------------------------------------------------------------------------------- /libraries/PID/PID_v1.h: -------------------------------------------------------------------------------- 1 | #ifndef PID_v1_h 2 | #define PID_v1_h 3 | #define LIBRARY_VERSION 1.1.1 4 | 5 | class PID 6 | { 7 | 8 | 9 | public: 10 | 11 | //Constants used in some of the functions below 12 | #define AUTOMATIC 1 13 | #define MANUAL 0 14 | #define DIRECT 0 15 | #define REVERSE 1 16 | #define P_ON_M 0 17 | #define P_ON_E 1 18 | 19 | //commonly used functions ************************************************************************** 20 | PID(double*, double*, double*, // * constructor. links the PID to the Input, Output, and 21 | double, double, double, int, int);// Setpoint. Initial tuning parameters are also set here. 22 | // (overload for specifying proportional mode) 23 | 24 | PID(double*, double*, double*, // * constructor. links the PID to the Input, Output, and 25 | double, double, double, int); // Setpoint. Initial tuning parameters are also set here 26 | 27 | void SetMode(int Mode); // * sets PID to either Manual (0) or Auto (non-0) 28 | 29 | bool Compute(); // * performs the PID calculation. it should be 30 | // called every time loop() cycles. ON/OFF and 31 | // calculation frequency can be set using SetMode 32 | // SetSampleTime respectively 33 | 34 | void SetOutputLimits(double, double); // * clamps the output to a specific range. 0-255 by default, but 35 | // it's likely the user will want to change this depending on 36 | // the application 37 | 38 | 39 | 40 | //available but not commonly used functions ******************************************************** 41 | void SetTunings(double, double, // * While most users will set the tunings once in the 42 | double); // constructor, this function gives the user the option 43 | // of changing tunings during runtime for Adaptive control 44 | void SetTunings(double, double, // * overload for specifying proportional mode 45 | double, int); 46 | 47 | void SetControllerDirection(int); // * Sets the Direction, or "Action" of the controller. DIRECT 48 | // means the output will increase when error is positive. REVERSE 49 | // means the opposite. it's very unlikely that this will be needed 50 | // once it is set in the constructor. 51 | void SetSampleTime(int); // * sets the frequency, in Milliseconds, with which 52 | // the PID calculation is performed. default is 100 53 | 54 | 55 | 56 | //Display functions **************************************************************** 57 | double GetKp(); // These functions query the pid for interal values. 58 | double GetKi(); // they were created mainly for the pid front-end, 59 | double GetKd(); // where it's important to know what is actually 60 | int GetMode(); // inside the PID. 61 | int GetDirection(); // 62 | 63 | private: 64 | void Initialize(); 65 | 66 | double dispKp; // * we'll hold on to the tuning parameters in user-entered 67 | double dispKi; // format for display purposes 68 | double dispKd; // 69 | 70 | double kp; // * (P)roportional Tuning Parameter 71 | double ki; // * (I)ntegral Tuning Parameter 72 | double kd; // * (D)erivative Tuning Parameter 73 | 74 | int controllerDirection; 75 | int pOn; 76 | 77 | double *myInput; // * Pointers to the Input, Output, and Setpoint variables 78 | double *myOutput; // This creates a hard link between the variables and the 79 | double *mySetpoint; // PID, freeing the user from having to constantly tell us 80 | // what these values are. with pointers we'll just know. 81 | 82 | unsigned long lastTime; 83 | double outputSum, lastInput; 84 | 85 | unsigned long SampleTime; 86 | double outMin, outMax; 87 | bool inAuto, pOnE; 88 | }; 89 | #endif 90 | 91 | -------------------------------------------------------------------------------- /libraries/PID/README.txt: -------------------------------------------------------------------------------- 1 | *************************************************************** 2 | * Arduino PID Library - Version 1.2.0 3 | * by Brett Beauregard brettbeauregard.com 4 | * 5 | * This Library is licensed under the MIT License 6 | *************************************************************** 7 | 8 | - For an ultra-detailed explanation of why the code is the way it is, please visit: 9 | http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/ 10 | 11 | - For function documentation see: http://playground.arduino.cc/Code/PIDLibrary 12 | -------------------------------------------------------------------------------- /libraries/PID/examples/PID_AdaptiveTunings/PID_AdaptiveTunings.ino: -------------------------------------------------------------------------------- 1 | /******************************************************** 2 | * PID Adaptive Tuning Example 3 | * One of the benefits of the PID library is that you can 4 | * change the tuning parameters at any time. this can be 5 | * helpful if we want the controller to be agressive at some 6 | * times, and conservative at others. in the example below 7 | * we set the controller to use Conservative Tuning Parameters 8 | * when we're near setpoint and more agressive Tuning 9 | * Parameters when we're farther away. 10 | ********************************************************/ 11 | 12 | #include 13 | 14 | #define PIN_INPUT 0 15 | #define PIN_OUTPUT 3 16 | 17 | //Define Variables we'll be connecting to 18 | double Setpoint, Input, Output; 19 | 20 | //Define the aggressive and conservative Tuning Parameters 21 | double aggKp=4, aggKi=0.2, aggKd=1; 22 | double consKp=1, consKi=0.05, consKd=0.25; 23 | 24 | //Specify the links and initial tuning parameters 25 | PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT); 26 | 27 | void setup() 28 | { 29 | //initialize the variables we're linked to 30 | Input = analogRead(PIN_INPUT); 31 | Setpoint = 100; 32 | 33 | //turn the PID on 34 | myPID.SetMode(AUTOMATIC); 35 | } 36 | 37 | void loop() 38 | { 39 | Input = analogRead(PIN_INPUT); 40 | 41 | double gap = abs(Setpoint-Input); //distance away from setpoint 42 | if (gap < 10) 43 | { //we're close to setpoint, use conservative tuning parameters 44 | myPID.SetTunings(consKp, consKi, consKd); 45 | } 46 | else 47 | { 48 | //we're far from setpoint, use aggressive tuning parameters 49 | myPID.SetTunings(aggKp, aggKi, aggKd); 50 | } 51 | 52 | myPID.Compute(); 53 | analogWrite(PIN_OUTPUT, Output); 54 | } 55 | 56 | 57 | -------------------------------------------------------------------------------- /libraries/PID/examples/PID_Basic/PID_Basic.ino: -------------------------------------------------------------------------------- 1 | /******************************************************** 2 | * PID Basic Example 3 | * Reading analog input 0 to control analog PWM output 3 4 | ********************************************************/ 5 | 6 | #include 7 | 8 | #define PIN_INPUT 0 9 | #define PIN_OUTPUT 3 10 | 11 | //Define Variables we'll be connecting to 12 | double Setpoint, Input, Output; 13 | 14 | //Specify the links and initial tuning parameters 15 | double Kp=2, Ki=5, Kd=1; 16 | PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT); 17 | 18 | void setup() 19 | { 20 | //initialize the variables we're linked to 21 | Input = analogRead(PIN_INPUT); 22 | Setpoint = 100; 23 | 24 | //turn the PID on 25 | myPID.SetMode(AUTOMATIC); 26 | } 27 | 28 | void loop() 29 | { 30 | Input = analogRead(PIN_INPUT); 31 | myPID.Compute(); 32 | analogWrite(PIN_OUTPUT, Output); 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /libraries/PID/examples/PID_PonM/PID_PonM.ino: -------------------------------------------------------------------------------- 1 | /******************************************************** 2 | * PID Proportional on measurement Example 3 | * Setting the PID to use Proportional on measurement will 4 | * make the output move more smoothly when the setpoint 5 | * is changed. In addition, it can eliminate overshoot 6 | * in certain processes like sous-vides. 7 | ********************************************************/ 8 | 9 | #include 10 | 11 | //Define Variables we'll be connecting to 12 | double Setpoint, Input, Output; 13 | 14 | //Specify the links and initial tuning parameters 15 | PID myPID(&Input, &Output, &Setpoint,2,5,1,P_ON_M, DIRECT); //P_ON_M specifies that Proportional on Measurement be used 16 | //P_ON_E (Proportional on Error) is the default behavior 17 | 18 | void setup() 19 | { 20 | //initialize the variables we're linked to 21 | Input = analogRead(0); 22 | Setpoint = 100; 23 | 24 | //turn the PID on 25 | myPID.SetMode(AUTOMATIC); 26 | } 27 | 28 | void loop() 29 | { 30 | Input = analogRead(0); 31 | myPID.Compute(); 32 | analogWrite(3,Output); 33 | } 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /libraries/PID/examples/PID_RelayOutput/PID_RelayOutput.ino: -------------------------------------------------------------------------------- 1 | /******************************************************** 2 | * PID RelayOutput Example 3 | * Same as basic example, except that this time, the output 4 | * is going to a digital pin which (we presume) is controlling 5 | * a relay. the pid is designed to Output an analog value, 6 | * but the relay can only be On/Off. 7 | * 8 | * to connect them together we use "time proportioning 9 | * control" it's essentially a really slow version of PWM. 10 | * first we decide on a window size (5000mS say.) we then 11 | * set the pid to adjust its output between 0 and that window 12 | * size. lastly, we add some logic that translates the PID 13 | * output into "Relay On Time" with the remainder of the 14 | * window being "Relay Off Time" 15 | ********************************************************/ 16 | 17 | #include 18 | 19 | #define PIN_INPUT 0 20 | #define RELAY_PIN 6 21 | 22 | //Define Variables we'll be connecting to 23 | double Setpoint, Input, Output; 24 | 25 | //Specify the links and initial tuning parameters 26 | double Kp=2, Ki=5, Kd=1; 27 | PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT); 28 | 29 | int WindowSize = 5000; 30 | unsigned long windowStartTime; 31 | 32 | void setup() 33 | { 34 | windowStartTime = millis(); 35 | 36 | //initialize the variables we're linked to 37 | Setpoint = 100; 38 | 39 | //tell the PID to range between 0 and the full window size 40 | myPID.SetOutputLimits(0, WindowSize); 41 | 42 | //turn the PID on 43 | myPID.SetMode(AUTOMATIC); 44 | } 45 | 46 | void loop() 47 | { 48 | Input = analogRead(PIN_INPUT); 49 | myPID.Compute(); 50 | 51 | /************************************************ 52 | * turn the output pin on/off based on pid output 53 | ************************************************/ 54 | if (millis() - windowStartTime > WindowSize) 55 | { //time to shift the Relay Window 56 | windowStartTime += WindowSize; 57 | } 58 | if (Output < millis() - windowStartTime) digitalWrite(RELAY_PIN, HIGH); 59 | else digitalWrite(RELAY_PIN, LOW); 60 | 61 | } 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /libraries/PID/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For PID Library 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | PID KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | SetMode KEYWORD2 16 | Compute KEYWORD2 17 | SetOutputLimits KEYWORD2 18 | SetTunings KEYWORD2 19 | SetControllerDirection KEYWORD2 20 | SetSampleTime KEYWORD2 21 | GetKp KEYWORD2 22 | GetKi KEYWORD2 23 | GetKd KEYWORD2 24 | GetMode KEYWORD2 25 | GetDirection KEYWORD2 26 | 27 | ####################################### 28 | # Constants (LITERAL1) 29 | ####################################### 30 | 31 | AUTOMATIC LITERAL1 32 | MANUAL LITERAL1 33 | DIRECT LITERAL1 34 | REVERSE LITERAL1 35 | P_ON_E LITERAL1 36 | P_ON_M LITERAL1 37 | -------------------------------------------------------------------------------- /libraries/PID/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PID", 3 | "keywords": "PID, controller, signal", 4 | "description": "A PID controller seeks to keep some input variable close to a desired setpoint by adjusting an output. The way in which it does this can be 'tuned' by adjusting three parameters (P,I,D).", 5 | "url": "http://playground.arduino.cc/Code/PIDLibrary", 6 | "include": "PID_v1", 7 | "authors": 8 | [ 9 | { 10 | "name": "Brett Beauregard" 11 | } 12 | ], 13 | "repository": 14 | { 15 | "type": "git", 16 | "url": "https://github.com/br3ttb/Arduino-PID-Library.git" 17 | }, 18 | "frameworks": "arduino" 19 | } 20 | -------------------------------------------------------------------------------- /libraries/PID/library.properties: -------------------------------------------------------------------------------- 1 | name=PID 2 | version=1.2.0 3 | author=Brett Beauregard 4 | maintainer=Brett Beauregard 5 | sentence=PID controller 6 | paragraph=A PID controller seeks to keep some input variable close to a desired setpoint by adjusting an output. The way in which it does this can be 'tuned' by adjusting three parameters (P,I,D). 7 | category=Signal Input/Output 8 | url=http://playground.arduino.cc/Code/PIDLibrary 9 | architectures=* 10 | -------------------------------------------------------------------------------- /libraries/readme.txt: -------------------------------------------------------------------------------- 1 | For information on installing libraries, see: http://arduino.cc/en/Guide/Libraries 2 | --------------------------------------------------------------------------------