diff --git a/HotWheels/HotWheels.ino b/HotWheels/HotWheels.ino index fd00b4a..d4e238d 100644 --- a/HotWheels/HotWheels.ino +++ b/HotWheels/HotWheels.ino @@ -1,34 +1,34 @@ -/* -Tuned Mass Dampner (TMD) code using Arduino UNO and Adafruit LIS3DH breakout board -More detials on TMD: https://www.microsoft.com/en-us/education/education-workshop/seismograph.aspx -More details on LIS3DH: https://www.adafruit.com/product/2809 - -This code captures accelerometer data over i2c, but not relying on any external libraries, and sends it over serial. - -Adi Azulay, 2017 Microsoft EDU Workshop -*/ +//===-------__ Hacking STEM – HotWheels_Accel.X.X.X.ino – Arduino __-------===// +// For use with the Measuring Speed to Understand Forces & Motion lesson plan +// available from Microsoft Education Workshop at http://aka.ms/hackingSTEM +// +// Overview: +// This project times the interval in milliseconds as cars pass between +// switch gates and then measures the gforce of the car impacting the +// accelerometer at the end stop. +// +// This may be implemented with 2 to 9 switch gates. The number of switch +// gates is configured by Excel via Serial connection. +// +// This project uses an Adafruit LIS3DH breakout board, information at: +// https://www.adafruit.com/product/2809 +// This project uses an Arduino UNO microcontroller board, information at: +// https://www.arduino.cc/en/main/arduinoBoardUno +// +// Comments, contributions, suggestions, bug reports, and feature requests +// are welcome! For source code and bug reports see: +// http://github.com/[TODO github path to Hacking STEM] +// +// Copyright 2018, Adi Azulay Microsoft EDU Workshop - HackingSTEM +// MIT License terms detailed in LICENSE.txt +//===----------------------------------------------------------------------===// +// Wire is a library that allows communication via i2c with devices such as +// the LIS3DH accelerometer. See https://www.arduino.cc/en/Reference/Wire #include - -// List of registers used by accelerometer -#define LIS3DH_ADDRESS 0x18 -#define LIS3DH_REG_STATUS1 0x07 -#define LIS3DH_REG_WHOAMI 0x0F -#define LIS3DH_REG_TEMPCFG 0x1F -#define LIS3DH_REG_CTRL1 0x20 -#define LIS3DH_REG_CTRL3 0x22 -#define LIS3DH_REG_CTRL4 0x23 -#define LIS3DH_REG_OUT_Y_L 0x2A -#define LIS3DH_REG_OUT_Y_H 0x2B - -#define LIS3DH_8G_SCALE_FACTOR .00024414f - -#define LIS3DH_RANGE_8_G 0b10 // +/- 8g - -/* - * Digital Pins for Gate Reading - */ +// Declaring constant variables to allow us to refer to pins by name, this +// makes code easier to understand. Here are all the gate pins. const byte gate1pin = 2; const byte gate2pin = 3; const byte gate3pin = 4; @@ -39,110 +39,77 @@ const byte gate7pin = 8; const byte gate8pin = 9; const byte gate9pin = 10; -/* -* Game Control Variables -*/ +// To time each gate we declare variable to allow us to track when the +// gate is triggered. +bool gate1state = LOW; //State of gate at last read +unsigned long gate1time = 0; //Time elapsed between start and last read +bool gate1done = false; //If gate was processed during current race - bool gate1state = 0; - unsigned long gate1time = 0; - bool gate1done=0; +bool gate2state = LOW; //State of gate at last read +unsigned long gate2time = 0; //Time elapsed between start and last read +bool gate2done = false; //If gate was processed during current race - bool gate2state = 0; - unsigned long gate2time = 0; - bool gate2done=0; +bool gate3state = LOW; //State of gate at last read +unsigned long gate3time = 0; //Time elapsed between start and last read +bool gate3done = false; //If gate was processed during current race - bool gate3state = 0; - unsigned long gate3time = 0; - bool gate3done=0; +bool gate4state = LOW; //State of gate at last read +unsigned long gate4time = 0; //Time elapsed between start and last read +bool gate4done = false; //If gate was processed during current race - bool gate4state = 0; - unsigned long gate4time = 0; - bool gate4done=0; +bool gate5state = LOW; //State of gate at last read +unsigned long gate5time = 0; //Time elapsed between start and last read +bool gate5done = false; //If gate was processed during current race - bool gate5state = 0; - unsigned long gate5time = 0; - bool gate5done=0; +bool gate6state = LOW; //State of gate at last read +unsigned long gate6time = 0; //Time elapsed between start and last read +bool gate6done = false; //If gate was processed during current race - bool gate6state = 0; - unsigned long gate6time = 0; - bool gate6done=0; +bool gate7state = LOW; //State of gate at last read +unsigned long gate7time = 0; //Time elapsed between start and last read +bool gate7done = false; //If gate was processed during current race - bool gate7state = 0; - unsigned long gate7time = 0; - bool gate7done=0; +bool gate8state = LOW; //State of gate at last read +unsigned long gate8time = 0; //Time elapsed between start and last read +bool gate8done = false; //If gate was processed during current race - bool gate8state = 0; - unsigned long gate8time = 0; - bool gate8done=0; +bool gate9state = LOW; //State of gate at last read +unsigned long gate9time = 0; //Time elapsed between start and last read +bool gate9done = false; //If gate was processed during current race - bool gate9state = 0; - unsigned long gate9time = 0; - bool gate9done=0; - bool force1done = 0; +// Race variables +unsigned long startTime = 0; // Millis timestamp of race start +bool raceFinished = false; // If final gate is completed +bool forceReadDone = false; // If force sensor is read +float gforce = 0; // Accelerometer force output - int prevValue = 0; - int value = 0; +// Config & control variables, set via Serial (by Excel) +// to configure and trigger race +int resetTrial = 0; //resets all variables +int numberOfGates = 3; //sets the final gate variable (overridden by Excel) - float force1time = 0; +// Serial data variables, used when sending and receiving data +const String mDELIMETER = ","; // comma delimited values +String mInputString = ""; // incoming data +boolean mStringComplete = false; // if incoming line is complete (newline found) +int mSerial_Interval = 50; // interval between serial writes +unsigned long mSerial_PreviousTime; // timestamp to track interval +const int dataRate = 10; // frequency of serial writes, in milliseconds -/* - * Program control variables -*/ -unsigned long startTime = 0; -byte raceFinished = 0; - -/* - * Excel program control variables - */ -int resetTrial = 0; //resets all variables -int numberOfGates = 9; //sets the final gate variable (overridden by Excel) - -/* - * Serial data variables - */ -const String mDELIMETER = ","; // Cordoba expects a comma delimeted string of data -String mInputString = ""; // string variable to hold incoming data -boolean mStringComplete = false; // variable to indicate the string is complete (newline found) -int mSerial_Interval = 50; // Intervel between serial writes -unsigned long mSerial_PreviousTime; // Timestamp to track interval - -const int dataRate = 10; // Change this variable to increase the frequency that data is sent to Excel +// setup() method is a special Arduino method that runs once at beginning of +// program. Typically used to initialize pins and connections void setup(){ - //Initilize LIS3DH and set to +/- 16g Scale Factor - Wire.begin(); - - Wire.beginTransmission(LIS3DH_ADDRESS); //Connects to LIS3DH via i2c - Wire.write (LIS3DH_REG_WHOAMI); //Check that board is connected - Wire.endTransmission(true); - Wire.requestFrom (LIS3DH_ADDRESS, 1); - uint8_t deviceID = Wire.read(); - - while (deviceID != 0x33){ - delay(1); - } - - writeRegister8 (LIS3DH_REG_CTRL1, 0x07); //Turn on all axes and set to normal mode - - //set data rate - uint8_t accelDataRate = readRegister8 (LIS3DH_REG_CTRL1); - accelDataRate &= ~(0xF0); - accelDataRate |= 0b0111 << 4; //Change variable to write - writeRegister8 (LIS3DH_REG_CTRL1, accelDataRate); //Set data rate to 400 mHz, used to manage power consuption - writeRegister8 (LIS3DH_REG_CTRL4, 0x88); //Enebles High Res and BDU - writeRegister8 (LIS3DH_REG_CTRL3, 0x10); // DRDY on INT1 - writeRegister8 (LIS3DH_REG_TEMPCFG, 0x80); //Activate ADC outputs - - //Set read scale - uint8_t rangeControl = readRegister8 (LIS3DH_REG_CTRL4); - rangeControl &= ~(0x30); - rangeControl |= LIS3DH_RANGE_8_G << 4; //Change variable to write make sure to also update the scale factor - writeRegister8 (LIS3DH_REG_CTRL4, rangeControl); + // initialized communication with accelerometer + // note, if accelerometer has problems, program can hange here + initializeAccelerometer(); + //initialize serial connection (to communicate with excel) Serial.begin (9600); + // Set each of our gate pins to be used as input pins pinMode(gate1pin, INPUT); pinMode(gate2pin, INPUT); pinMode(gate3pin, INPUT); @@ -153,20 +120,27 @@ void setup(){ pinMode(gate8pin, INPUT); pinMode(gate9pin, INPUT); + // Reset all race variable, so we're ready to go! resetTrialVariables(); } + + +// loop() method is a special Arduino function that runs over and over. This +// function executes from top to bottom and then starts again, it runs forever! void loop(){ - processIncomingSerial(); - if(resetTrial==1){ + processIncomingSerial(); // See if any commands have come in (from Excel) + if(resetTrial==1){ // If a race was already run, clear old data resetTrialVariables(); } - processDigitalSensors(); - processSwitches(); - processForceSensor(); - processOutgoingSerial(); + processDigitalSensors(); // Read all gate switches + processSwitches(); // Process any changes to switch state + processForceSensor(); // Read force sensor + processOutgoingSerial(); // Write any results to Serial (to Excel) } + +// Quickly read state of each gate switch pin and write it to variables void processDigitalSensors(){ gate1state = digitalRead(gate1pin); gate2state = digitalRead(gate2pin); @@ -178,233 +152,238 @@ void processDigitalSensors(){ gate8state = digitalRead(gate8pin); gate9state = digitalRead(gate9pin); } + + +// Examine gate switch pine state and update timing if triggered void processSwitches(){ - // Digitial switch reads - if(raceFinished==0){ - if(gate1state==HIGH && gate1done==0){ + if(raceFinished==false){ + // If first gate is triggered, we set startTime to current + // timestamp, in milliseconds. + if(gate1state==HIGH && gate1done==false){ gate1time = 0; - gate1done=1; + gate1done=true; startTime = millis(); } - if(gate2state==HIGH && gate2done==0){ + // When gate is triggered we calculate the elapsed time since + // the first gate was triggered + if(gate2state==HIGH && gate2done==false){ gate2time = millis() - startTime; - gate2done=1; - if(numberOfGates==2){ - raceFinished = 1; + gate2done=true; + if(numberOfGates==2){ // If this is last gate, race as finished + raceFinished = true; } } - if(gate3state==HIGH && gate3done==0){ + // When gate is triggered we calculate the elapsed time since + // the first gate was triggered + if(gate3state==HIGH && gate3done==false){ gate3time = millis() - startTime; - gate3done=1; - if(numberOfGates==3){ - raceFinished = 1; + gate3done=true; + if(numberOfGates==3){ // If this is last gate, race as finished + raceFinished = true; } } - if(gate4state==HIGH && gate4done==0){ + // When gate is triggered we calculate the elapsed time since + // the first gate was triggered + if(gate4state==HIGH && gate4done==false){ gate4time = millis() - startTime; - gate4done=1; - if(numberOfGates==4){ - raceFinished = 1; + gate4done=true; + if(numberOfGates==4){ // If this is last gate, race as finished + raceFinished = true; } } - if(gate5state==HIGH && gate5done==0){ + // When gate is triggered we calculate the elapsed time since + // the first gate was triggered + if(gate5state==HIGH && gate5done==false){ gate5time = millis() - startTime; - gate5done=1; - if(numberOfGates==5){ - raceFinished = 1; + gate5done=true; + if(numberOfGates==5){ // If this is last gate, race as finished + raceFinished = true; } } - if(gate6state==HIGH && gate6done==0){ + // When gate is triggered we calculate the elapsed time since + // the first gate was triggered + if(gate6state==HIGH && gate6done==false){ gate6time = millis() - startTime; - gate6done=1; - if(numberOfGates==6){ - raceFinished = 1; + gate6done=true; + if(numberOfGates==6){ // If this is last gate, race as finished + raceFinished = true; } } - if(gate7state==HIGH && gate7done==0){ + // When gate is triggered we calculate the elapsed time since + // the first gate was triggered + if(gate7state==HIGH && gate7done==false){ gate7time = millis() - startTime; - gate7done=1; - if(numberOfGates==7){ - raceFinished = 1; + gate7done=true; + if(numberOfGates==7){ // If this is last gate, race as finished + raceFinished = true; } } - if(gate8state==HIGH && gate8done==0){ + // When gate is triggered we calculate the elapsed time since + // the first gate was triggered + if(gate8state==HIGH && gate8done==false){ gate8time = millis() - startTime; - gate8done=1; - if(numberOfGates==8){ - raceFinished = 1; + gate8done=true; + if(numberOfGates==8){ // If this is last gate, race as finished + raceFinished = true; } } - if(gate9state==HIGH && gate9done==0){ + // When gate is triggered we calculate the elapsed time since + // the first gate was triggered + if(gate9state==HIGH && gate9done==false){ gate9time = millis() - startTime; - gate9done=1; - if(numberOfGates==9){ - raceFinished = 1; + gate9done=true; + if(numberOfGates==9){ // If this is last gate, race as finished + raceFinished = true; } } } } + +// If race is finished poll force sensor for a reading void processForceSensor(){ - float maxYAxis = 0; - if(raceFinished==1 && force1done==0) - { - for (int i = 0; i <= 100; i++){ - Wire.beginTransmission(LIS3DH_ADDRESS); - Wire.write(LIS3DH_REG_OUT_Y_L | 0x80); - Wire.endTransmission(); - - Wire.requestFrom(LIS3DH_ADDRESS, 2); - while (Wire.available() < 2); - - uint8_t yla = Wire.read(); - uint8_t yha = Wire.read(); - - float yAxis = yha << 8 | yla; - - yAxis = yAxis * LIS3DH_8G_SCALE_FACTOR; - if (yAxis > maxYAxis) {maxYAxis = yAxis;} - - delay (1); - } - force1time = maxYAxis; //get the time interval passed during impact (for Excel) - force1done = 1; + if(raceFinished==true && forceReadDone==false) { + gforce = getMaxYAxisReadFromForceSensor(); // get force reading + forceReadDone = true; } } +// Resets all variables so we're ready to run another race trail void resetTrialVariables(){ - raceFinished = 0; - force1done = 0; + raceFinished = false; + forceReadDone = false; gate1time = 999; - gate1done=0; + gate1done = false; gate2time = 0; - gate2done=0; + gate2done = false; gate3time = 0; - gate3done=0; + gate3done = false; gate4time = 0; - gate4done=0; + gate4done = false; gate5time = 0; - gate5done=0; + gate5done = false; gate6time = 0; - gate6done=0; + gate6done = false; gate7time = 0; - gate7done=0; + gate7done = false; gate8time = 0; - gate8done=0; + gate8done = false; gate9time = 0; - gate9done=0; + gate9done = false; - force1time = 0; + gforce = 0; resetTrial = 0; } -/* - * ------------------------------------------------------------------------------------------------------- - * INCOMING SERIAL DATA FROM EXCEL PROCESSING CODE-------------------------------------------------------- - * ------------------------------------------------------------------------------------------------------- - */ - -void processIncomingSerial() -{ +// Read any lines of text, if available and parse commands and configuration +void processIncomingSerial() { getSerialData(); parseSerialData(); } -/* - * getSerialData() - * - * Gathers bits from serial port to build mInputString - */ -void getSerialData() -{ - while (Serial.available()) { - char inChar = (char)Serial.read(); // get new byte - mInputString += inChar; // add it to input string - if (inChar == '\n') { // if we get a newline... - mStringComplete = true; // we have a complete string of data to process - } - } -} - -/* - * parseSerialData() - * - * Parse all program control variables and data from Excel - */ -void parseSerialData() -{ - if (mStringComplete) { // process data from mInputString to set program variables. - //set variables using: var = getValue(mInputString, ',', index).toInt(); // see getValue function below - - resetTrial = getValue(mInputString, ',', 0).toInt(); // Data Out column A5 - - String data = getValue(mInputString, ',', 1); // Data Out column B5 - if(data != ""){ - numberOfGates = data.toInt(); //getValue(mInputString, ',', 1); //.toInt(); // Data Out column B5 - } - - mInputString = ""; // reset mInputString - mStringComplete = false; // reset stringComplete flag - } -} - -/* - * getValue() - * - * Gets value from mInputString using an index. Each comma delimited value in mInputString - * is counted and the value of the matching index is returned. - */ -String getValue(String mDataString, char separator, int index) -{ - // mDataString is mInputString, separator is a comma, index is where we want to look in the data 'array' - int matchingIndex = 0; - int strIndex[] = {0, -1}; - int maxIndex = mDataString.length()-1; - for(int i=0; i<=maxIndex && matchingIndex<=index; i++){ // loop until end of array or until we find a match - if(mDataString.charAt(i)==separator || i==maxIndex){ // if we hit a comma OR we are at the end of the array - matchingIndex++; // increment matchingIndex to keep track of where we have looked - strIndex[0] = strIndex[1]+1; // increment first substring index - // ternary operator in objective c - [condition] ? [true expression] : [false expression] - strIndex[1] = (i == maxIndex) ? i+1 : i; // set second substring index - } - } - return matchingIndex>index ? mDataString.substring(strIndex[0], strIndex[1]) : ""; // if match return substring or "" -} - -/* - * ------------------------------------------------------------------------------------------------------- - * OUTGOING SERIAL DATA TO EXCEL PROCESSING CODE---------------------------------------------------------- - * ------------------------------------------------------------------------------------------------------- - */ -void processOutgoingSerial() -{ - if((millis() - mSerial_PreviousTime) > mSerial_Interval) // Write at intervals to prevent bogging down script +// Writes data to Serial (for excel) at a maximum rate of mSerial_Interval +void processOutgoingSerial() { + // Write at intervals to prevent bogging down script + if((millis() - mSerial_PreviousTime) > mSerial_Interval) { mSerial_PreviousTime = millis(); // Reset interval timestamp sendDataToSerial(); } } -void sendDataToSerial() -{ + +//===----------------------------------------------------------------------===// +// Note: Code below this line may be technical and somewhat confusing, the +// purpose of these functions are to do some complicated things such as +// interfacing with external devices. +// +// To communicate with LIS3DH without requiring external libraries, we had +// to implement some code in this section may seem very cryptic! Don't worry +// it's hard for us to understand as well :) +//===----------------------------------------------------------------------===// + + +// Looks Serial data and read it character by character into a string +void getSerialData() { + while (Serial.available()) { + char inChar = (char)Serial.read(); // get new byte + mInputString += inChar; // add it to input string + if (inChar == '\n') { // if we get a newline... + mStringComplete = true; // we have a complete string of data to process + } + } +} + + +// Take input string and parse commands and configuration +void parseSerialData() { + if (mStringComplete) { // process data from mInputString to set variables. + resetTrial = getValue(mInputString, ',', 0).toInt(); // Data Out column A5 + String data = getValue(mInputString, ',', 1); // Data Out column B5 + if(data != ""){ + numberOfGates = data.toInt(); // convert to integer, if not empty + } + + mInputString = ""; // reset mInputString + mStringComplete = false; // reset stringComplete flag + } +} + + +// Gets value from mDataString using an index and separator +// Example: +// given 'alice,bob,dana' and separator ',' +// index 0 returns 'alice' +// index 1 returns 'bob' +// index 2 returns 'dana' +// +// mDataString: String as read from Serial (mInputString) +// separator: Character used to separate values (a comma) +// index: where we want to look in the data 'array' for value +String getValue(String mDataString, char separator, int index) { + int matchingIndex = 0; + int strIndex[] = {0, -1}; + int maxIndex = mDataString.length()-1; + // loop until end of array or until we find a match + for(int i=0; i<=maxIndex && matchingIndex<=index; i++){ + if(mDataString.charAt(i)==separator || i==maxIndex){ // if we hit a comma + // OR end of the array + matchingIndex++; // increment to track where we have looked + strIndex[0] = strIndex[1]+1; // increment first substring index + strIndex[1] = (i == maxIndex) ? i+1 : i; // set second substring index + } + } + // if match return substring or "" + if (matchingIndex > index) { + return mDataString.substring(strIndex[0], strIndex[1]); + } else { + return ""; + } +} + +// Constructs comma delimited list of gate times and force, then writes it +// to serial (for Excel). +// Writes 9 gate time stamps and one force +// example 11225,13535,18929,0,0,0,0,0,2.3223 +void sendDataToSerial() { //gate times in milliseconds Serial.print(gate1time); Serial.print(mDELIMETER); @@ -433,13 +412,87 @@ void sendDataToSerial() Serial.print(gate9time); Serial.print(mDELIMETER); - //force time in microseconds - Serial.print(force1time); + Serial.print(gforce); Serial.print(mDELIMETER); Serial.println(); // Line ending character } +// List of registers used by accelerometer +#define LIS3DH_ADDRESS 0x18 +#define LIS3DH_REG_STATUS1 0x07 +#define LIS3DH_REG_WHOAMI 0x0F +#define LIS3DH_REG_TEMPCFG 0x1F +#define LIS3DH_REG_CTRL1 0x20 +#define LIS3DH_REG_CTRL3 0x22 +#define LIS3DH_REG_CTRL4 0x23 +#define LIS3DH_REG_OUT_Y_L 0x2A +#define LIS3DH_REG_OUT_Y_H 0x2B +#define LIS3DH_8G_SCALE_FACTOR .00024414f +#define LIS3DH_RANGE_8_G 0b10 // +/- 8g + + +// Initilize LIS3DH see LIS3DH spec sheet +void initializeAccelerometer() { + Wire.begin(); + Wire.beginTransmission(LIS3DH_ADDRESS); //Connects to LIS3DH via i2c + Wire.write (LIS3DH_REG_WHOAMI); //Check that board is connected + Wire.endTransmission(true); + Wire.requestFrom (LIS3DH_ADDRESS, 1); + uint8_t deviceID = Wire.read(); + + while (deviceID != 0x33){ + delay(1); // TODO review looks like a bug... hangs forever if no LIS3DH on first Wire.read() should at least write "No LISD3H" to serial while it hangs + } + + //Turn on all axes and set to normal mode + writeRegister8 (LIS3DH_REG_CTRL1, 0x07); + + //set data rate + uint8_t accelDataRate = readRegister8 (LIS3DH_REG_CTRL1); + accelDataRate &= ~(0xF0); + accelDataRate |= 0b0111 << 4; //Change variable to write + + //Set data rate to 400 mHz, used to manage power consumption + writeRegister8 (LIS3DH_REG_CTRL1, accelDataRate); + writeRegister8 (LIS3DH_REG_CTRL4, 0x88); //Enebles High Res and BDU + writeRegister8 (LIS3DH_REG_CTRL3, 0x10); // DRDY on INT1 + writeRegister8 (LIS3DH_REG_TEMPCFG, 0x80); //Activate ADC outputs + + //Set read scale + uint8_t rangeControl = readRegister8 (LIS3DH_REG_CTRL4); + rangeControl &= ~(0x30); + //Change variable to write make sure to also update the scale factor + rangeControl |= LIS3DH_RANGE_8_G << 4; + writeRegister8 (LIS3DH_REG_CTRL4, rangeControl); +} + +// Reads Y axis force values from accelerometer and returns +// the highest of 100 sequential reads over a 100ms timespan +float getMaxYAxisReadFromForceSensor() { + float maxYAxis = 0; + for (int i = 0; i <= 100; i++){ + Wire.beginTransmission(LIS3DH_ADDRESS); + Wire.write(LIS3DH_REG_OUT_Y_L | 0x80); + Wire.endTransmission(); + + Wire.requestFrom(LIS3DH_ADDRESS, 2); + while (Wire.available() < 2); + + uint8_t yla = Wire.read(); + uint8_t yha = Wire.read(); + + float yAxis = yha << 8 | yla; + + yAxis = yAxis * LIS3DH_8G_SCALE_FACTOR; + if (yAxis > maxYAxis) {maxYAxis = yAxis;} + + delay (1); + } + return maxYAxis; +} + +// configuration of accelerometer, LIS3DH datasheet void writeRegister8 (uint8_t reg, uint8_t val){ Wire.beginTransmission (LIS3DH_ADDRESS); Wire.write (reg); @@ -447,6 +500,7 @@ void writeRegister8 (uint8_t reg, uint8_t val){ Wire.endTransmission(); } +// configuration of accelerometer, LIS3DH datasheet uint8_t readRegister8 (uint8_t reg){ Wire.beginTransmission (LIS3DH_ADDRESS); Wire.write (reg); @@ -456,5 +510,4 @@ uint8_t readRegister8 (uint8_t reg){ uint8_t val = Wire.read(); return val; Wire.endTransmission(); - } diff --git a/README.md b/README.md index a4579b6..a711f06 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,18 @@ -# Introduction -TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project. +# Introduction +Arduino code for Microsoft Hacking STEM Hot Wheels Speedometry Lesson Plan adapted for Arduino # Getting Started -TODO: Guide users through getting your code up and running on their own system. In this section you can talk about: -1. Installation process -2. Software dependencies -3. Latest releases -4. API references +1. Download lesson assets at http://aka.ms/hackingSTEM +1. Build your Hot Wheels track! +1. Use [Arduino IDE](https://www.arduino.cc/en/Main/Software) to the .ino to your [Arduino Uno](https://store.arduino.cc/usa/arduino-uno-rev3) microcontroller +1. Verify data interactions in Excel +1. Ready, Set, Science! -# Build and Test -TODO: Describe and show how to build your code and run the tests. +# Contributing +We gladly accept pull requests for enhancements and bug fixes! You may also submit feature requests and bugs! +https://github.com/TODO -# Contribute -TODO: Explain how other users and developers can contribute to make your code better. +# Make it your! +This project is licensed under the MIT open source license, see License.txt. The MIT license allows you to take this project and make awesome things with it! MIT is a very permissive license, but does require you include license and copyright from License.txt in any derivative work for sake of attribution. -If you want to learn more about creating good readme files then refer the following [guidelines](https://www.visualstudio.com/en-us/docs/git/create-a-readme). You can also seek inspiration from the below readme files: -- [ASP.NET Core](https://github.com/aspnet/Home) -- [Visual Studio Code](https://github.com/Microsoft/vscode) -- [Chakra Core](https://github.com/Microsoft/ChakraCore) \ No newline at end of file +Fork away! Let us know what you build!