diff --git a/README.md b/README.md index 627657f..e210fe5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# SparkFun_Template_Arduino_Library +# SparkFun_Qwiic_Ultrasonic_Arduino_Library ======================================== diff --git a/documents/HC_SR04_Datasheet.pdf b/documents/HC_SR04_Datasheet.pdf new file mode 100644 index 0000000..fcd6f54 Binary files /dev/null and b/documents/HC_SR04_Datasheet.pdf differ diff --git a/documents/add_documents_here.md b/documents/add_documents_here.md deleted file mode 100644 index 2010408..0000000 --- a/documents/add_documents_here.md +++ /dev/null @@ -1 +0,0 @@ -Add any relevant documents to this director (eg. datasheet), and delete this file. diff --git a/examples/Example01_BasicUsage/Example01_BasicUsage.ino b/examples/Example01_BasicUsage/Example01_BasicUsage.ino deleted file mode 100644 index b308416..0000000 --- a/examples/Example01_BasicUsage/Example01_BasicUsage.ino +++ /dev/null @@ -1,22 +0,0 @@ -// TODO: Add includes as needed -#include "SparkFun_Template_Arduino_Library.h" - -// TODO: Change Template -TempalteClass myDevice; - -void setup() -{ - // Start serial - Serial.begin(115200); - Serial.println("Template Example 1 - Basic Uasge"); // TODO: Update - - // TODO: Check return value of begin - myDevice.begin(); - - // TODO: Add other setup code if needed. Most setup should be done in begin() -} - -void loop() -{ - // TODO: Demonstrate minimal code needed for basic usage -} \ No newline at end of file diff --git a/examples/Example1_BasicReadings/Example1_BasicReadings.ino b/examples/Example1_BasicReadings/Example1_BasicReadings.ino new file mode 100644 index 0000000..73cfe8b --- /dev/null +++ b/examples/Example1_BasicReadings/Example1_BasicReadings.ino @@ -0,0 +1,44 @@ +#include "SparkFun_Qwiic_Ultrasonic_Arduino_Library.h" + +// Create an ultrasonic sensor object +QwiicUltrasonic myUltrasonic; + +// Here we set the device address. Note that an older version of the Qwiic +// Ultrasonic firmware used a default address of 0x00. If yours uses 0x00, +// you'll need to change the address below. It is also recommended to run +// Example 2 to change the address to the new default. +uint8_t deviceAddress = kQwiicUltrasonicDefaultAddress; // 0x2F +// uint8_t deviceAddress = 0x00; + +void setup() +{ + // Start serial + Serial.begin(115200); + Serial.println("Qwiic Ultrasonic Example 1 - Basic Readings"); + + Wire.begin(); + + // Attempt to begin the sensor + while (myUltrasonic.begin(deviceAddress) == false) + { + Serial.println("Ultrasonic sensor not connected, check your wiring and I2C address!"); + delay(1000); + } + + Serial.println("Ultrasonic sensor connected!"); +} + +void loop() +{ + // Get measurement from sensor. Note that the mesaured distance actually + // comes from the previous trigger, so measurements will be slightly delayed + uint16_t distance = 0; + myUltrasonic.triggerAndRead(distance); + + // Print measurement + Serial.print("Distance (mm): "); + Serial.println(distance); + + // Wait a bit + delay(100); +} \ No newline at end of file diff --git a/examples/Example2_ChangeAddress/Example2_ChangeAddress.ino b/examples/Example2_ChangeAddress/Example2_ChangeAddress.ino new file mode 100644 index 0000000..c94577c --- /dev/null +++ b/examples/Example2_ChangeAddress/Example2_ChangeAddress.ino @@ -0,0 +1,94 @@ +#include "SparkFun_Qwiic_Ultrasonic_Arduino_Library.h" + +// Create an ultrasonic sensor object +QwiicUltrasonic myUltrasonic; + +// Here we set the device address. Note that an older version of the Qwiic +// Ultrasonic firmware used a default address of 0x00. If yours uses 0x00, +// you'll need to change the address below. It is also recommended to run +// Example 2 to change the address to the new default. +uint8_t deviceAddress = kQwiicUltrasonicDefaultAddress; // 0x2F +// uint8_t deviceAddress = 0x00; + +void setup() +{ + // Start serial + Serial.begin(115200); + Serial.println("Qwiic Ultrasonic Example 2 - Change Address"); + + Wire.begin(); + + // Attempt to begin the sensor + while (myUltrasonic.begin(deviceAddress) == false) + { + Serial.println("Ultrasonic sensor not connected, check your wiring and I2C address!"); + delay(1000); + } + + Serial.println("Ultrasonic sensor connected!"); + + // Repeat until the address has been successfully changed + bool addressChanged = false; + while (addressChanged == false) + { + // Print instructions + Serial.println(); + Serial.println("Please enter a new address for the sensor."); + Serial.println("Any value between 0x20 and 0x2F is valid."); + Serial.println("Enter the address in hexadecimal without the `0x`."); + Serial.println(); + + // Clear serial buffer and wait for input + while (Serial.available() > 0) + Serial.read(); + while (Serial.available() == 0) + ; + + // Read input from user + char input[4]; // Only expecting a few characters + size_t numBytesRead = Serial.readBytesUntil('\n', input, 4); + + // Parse input using strtoul (STRing TO Unsigned Long integer) + uint8_t newAddress = strtoul(input, nullptr, 16); + + Serial.print("Parsed address: "); + Serial.println(newAddress, HEX); + + // Check if the address is valid + if (newAddress < kQwiicUltrasonicMinAddress || newAddress > kQwiicUltrasonicMaxAddress) + { + Serial.println("Invalid address!"); + continue; + } + + // Address is valid, attempt to change it on the device + sfeTkError_t err = myUltrasonic.changeAddress(newAddress); + + // Check whether the address was changed successfully + if (err) + Serial.println("Failed to change address!"); + + // Success, we're done here! + addressChanged = true; + } + + Serial.println("Address changed successfully! Continuing..."); + + // Wait a moment so user can read the messages + delay(1000); +} + +void loop() +{ + // Get measurement from sensor. Note that the mesaured distance actually + // comes from the previous trigger, so measurements will be slightly delayed + uint16_t distance = 0; + myUltrasonic.triggerAndRead(distance); + + // Print measurement + Serial.print("Distance (mm): "); + Serial.println(distance); + + // Wait a bit + delay(100); +} \ No newline at end of file diff --git a/keywords.txt b/keywords.txt index 2344c7f..a4091f6 100644 --- a/keywords.txt +++ b/keywords.txt @@ -1,29 +1,27 @@ ######################################################### -# Syntax Coloring Map for TODO: Add name # +# Syntax Coloring Map for the Qwiic Ultrasonic Sensor # ######################################################### # Class ######################################################### -# TODO: Add this -TemplateClass KEYWORD1 +QwiicUltrasonic KEYWORD1 ######################################################### # Methods and Functions ######################################################### -# TODO: Add these begin KEYWORD2 +isConnected KEYWORD2 +triggerAndRead KEYWORD2 +changeAddress KEYWORD2 ######################################################### # Constants ######################################################### -# TODO: Add these -TEMPALTE_CONSTANT LITERAL1 - -######################################################### -# Structs -######################################################### - -# TODO: Add these -template_struct_t LITERAL3 \ No newline at end of file +QWIIC_ULTRASONIC_ADDRESSES LITERAL1 +QWIIC_ULTRASONIC_NUM_ADDRESSES LITERAL1 +QWIIC_ULTRASONIC_MIN_ADDRESS LITERAL1 +QWIIC_ULTRASONIC_MAX_ADDRESS LITERAL1 +QWIIC_ULTRASONIC_DEFAULT_ADDRESS LITERAL1 +QWIIC_ULTRASONIC_REGISTER_TRIGGER LITERAL1 diff --git a/library.properties b/library.properties index a1a6c01..bf9d5be 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ -name=SparkFun Template Arduino Library +name=SparkFun Qwiic Ultrasonic Arduino Library version=1.0.0 author=SparkFun Electronics maintainer=SparkFun Electronics -sentence=TODO: Add short description -paragraph=TODO: Add long description -category=TODO: Add category (Sensors, Display, Communication, etc.) -url=TODO: Add URL -architectures=TODO: Add architectures (*, esp32, teensy, stm32, megaavr, etc.) \ No newline at end of file +sentence=A library to use the SparkFun Qwiic Ultrasonic Distance Sensor +paragraph= +category=Sensors +url=https://github.com/sparkfun/SparkFun_Qwiic_Ultrasonic_Arduino_Library +architectures=* \ No newline at end of file diff --git a/src/SparkFun_Qwiic_Ultrasonic_Arduino_Library.h b/src/SparkFun_Qwiic_Ultrasonic_Arduino_Library.h new file mode 100644 index 0000000..494fd9d --- /dev/null +++ b/src/SparkFun_Qwiic_Ultrasonic_Arduino_Library.h @@ -0,0 +1,32 @@ +#pragma once + +#include "Arduino.h" +#include "sfeQwiicUltrasonic.h" +#include + +class QwiicUltrasonic : public sfeQwiicUltrasonic +{ + public: + /// @brief Begins the Qwiic Ultrasonic sensor + /// @param address I2C device address to use for the sensor + /// @param wirePort Wire port to use for I2C communication + /// @return True if successful, false otherwise + bool begin(uint8_t address = kQwiicUltrasonicDefaultAddress, TwoWire &wirePort = Wire) + { + // Setup Arudino I2C bus + _theI2CBus.init(wirePort, address); + + // Begin the sensor + return sfeQwiicUltrasonic::begin(&_theI2CBus) == kSTkErrOk; + } + + /// @brief Checks if the Qwiic Ultrasonic sensor is connected + /// @return True if the sensor is connected, false otherwise + bool isConnected() + { + return sfeQwiicUltrasonic::isConnected() == kSTkErrOk; + } + + private: + sfeTkArdI2C _theI2CBus; +}; diff --git a/src/SparkFun_Template_Arduino_Library.cpp b/src/SparkFun_Template_Arduino_Library.cpp deleted file mode 100644 index f27ea73..0000000 --- a/src/SparkFun_Template_Arduino_Library.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "SparkFun_Template_Arduino_Library.h" - -BMI270::BMI270() -{ - // TODO: Initialize variables -} - -int8_t BMI270::begin() -{ - // TODO: Check if device is connected - - // TODO: Initialize hardware - - // TODO: Return whether successful - return false; -} diff --git a/src/SparkFun_Template_Arduino_Library.h b/src/SparkFun_Template_Arduino_Library.h deleted file mode 100644 index f7756e2..0000000 --- a/src/SparkFun_Template_Arduino_Library.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -// TODO: Add includes as needed (e.g. #include , #include ) -#include "Arduino.h" - -// TODO: Add constants - -// TODO: Implement class -class TemplateClass -{ - public: - /// @brief TODO - TemplateClass(); - - /// @brief TODO - /// @return TODO - bool begin(); - - // TODO: Add other methods as needed -}; diff --git a/src/sfeQwiicUltrasonic.cpp b/src/sfeQwiicUltrasonic.cpp new file mode 100644 index 0000000..d9b450b --- /dev/null +++ b/src/sfeQwiicUltrasonic.cpp @@ -0,0 +1,74 @@ +#include "sfeQwiicUltrasonic.h" + +sfeTkError_t sfeQwiicUltrasonic::begin(sfeTkII2C *theBus) +{ + // Nullptr check + if (theBus == nullptr) + return kSTkErrFail; + + // Check the device address + if (theBus->address() < kQwiicUltrasonicMinAddress || theBus->address() > kQwiicUltrasonicMaxAddress) + { + // An older version of the firmware used 0x00 as the default address. + // It's not really a valid address, but we need to allow it. Any other + // address can't be used + if (theBus->address() != 0x00) + return kSTkErrFail; + } + + // Set bus pointer + _theBus = theBus; + + // Just check if the device is connected, no other setup is needed + return isConnected(); +} + +sfeTkError_t sfeQwiicUltrasonic::isConnected() +{ + // Just ping the device address, there's no product ID register to check + return _theBus->ping(); +} + +sfeTkError_t sfeQwiicUltrasonic::triggerAndRead(uint16_t &distance) +{ + size_t bytesRead = 0; + uint8_t rawData[2] = {0, 0}; + + // Attempt to read the distance + sfeTkError_t err = _theBus->readRegisterRegion(kQwiicUltrasonicRegisterTrigger, rawData, 2, bytesRead); + + // Check whether the read was successful + if (err != kSTkErrOk) + return err; + + // Store raw data + distance = (rawData[0] << 8) | rawData[1]; + + // Done! + return kSTkErrOk; +} + +sfeTkError_t sfeQwiicUltrasonic::changeAddress(const uint8_t &address) +{ + // Check whether the address is valid + if (address < kQwiicUltrasonicMinAddress || address > kQwiicUltrasonicMaxAddress) + return kSTkErrFail; + + // Write the new address to the device. The first bit must be set to 1 + sfeTkError_t err = _theBus->writeByte(address | 0x80); + + // Check whether the write was successful + if (err != kSTkErrOk) + return err; + + // Update the address in the bus + _theBus->setAddress(address); + + // Done! + return kSTkErrOk; +} + +uint8_t sfeQwiicUltrasonic::getAddress() +{ + return _theBus->address(); +} diff --git a/src/sfeQwiicUltrasonic.h b/src/sfeQwiicUltrasonic.h new file mode 100644 index 0000000..376a354 --- /dev/null +++ b/src/sfeQwiicUltrasonic.h @@ -0,0 +1,50 @@ +#pragma once + +#include "SparkFun_Toolkit.h" +#include + +// Available I2C addresses of the Qwiic Ultrasonic +const uint8_t kQwiicUltrasonicAddresses[] = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F}; +const uint8_t kQwiicUltrasonicNumAddresses = sizeof(kQwiicUltrasonicAddresses) / sizeof(uint8_t); +const uint8_t kQwiicUltrasonicMinAddress = kQwiicUltrasonicAddresses[0]; +const uint8_t kQwiicUltrasonicMaxAddress = kQwiicUltrasonicAddresses[15]; +const uint8_t kQwiicUltrasonicDefaultAddress = 0x2F; + +// Register to trigger a new measuremnt and read the previous one +const uint8_t kQwiicUltrasonicRegisterTrigger = 0x01; + +class sfeQwiicUltrasonic +{ + public: + /// @brief Default constructor + sfeQwiicUltrasonic() : _theBus(nullptr) + { + } + + /// @brief Begins the Qwiic Ultrasonic sensor + /// @param theBus I2C bus to use for communication + /// @return 0 for succuss, negative for errors, positive for warnings + sfeTkError_t begin(sfeTkII2C *theBus = nullptr); + + /// @brief Checks if the Qwiic Ultrasonic sensor is connected + /// @return 0 for succuss, negative for errors, positive for warnings + sfeTkError_t isConnected(); + + /// @brief Triggers a new measurement and reads the previous one + /// @param distance Distance in mm + /// @return 0 for succuss, negative for errors, positive for warnings + sfeTkError_t triggerAndRead(uint16_t &distance); + + /// @brief Changes the I2C address of the Qwiic Ultrasonic sensor + /// @param address New address, must be in the range 0x20 to 0x2F + /// @return 0 for succuss, negative for errors, positive for warnings + sfeTkError_t changeAddress(const uint8_t &address); + + /// @brief Gets the current I2C address of the Qwiic Ultrasonic sensor + /// @return The current I2C address, 7-bit unshifted + uint8_t getAddress(); + + protected: + sfeTkII2C *_theBus; +};