├── LICENSE ├── README.md ├── doc ├── CS5530-Module-24-bit-ADC.jpg └── CS5530.pdf ├── examples ├── CS5530_basic │ └── CS5530_basic.ino └── CS5530_setFrequency │ └── CS5530_setFrequency.ino ├── keywords.txt ├── library.properties └── src ├── CS5530.cpp └── CS5530.h /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Yasir Shahzad 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arduino CS5530 2 | [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT) 3 | [![Installation instructions](https://www.ardu-badge.com/badge/CS5530.svg?)](https://www.ardu-badge.com/CS5530) 4 | [![Commits since latest](https://img.shields.io/github/commits-since/yasir-shahzad/CS5530/latest)](https://github.com/yasir-shahzad/CS5530/commits/master) 5 | [![Build Status](https://github.com/yasir-shahzad/CS5530/workflows/LibraryBuild/badge.svg)](https://github.com/yasir-shahzad/CS5530/actions) 6 | ![Hit Counter](https://visitor-badge.laobi.icu/badge?page_id=yasir-shahzad_CS5530) 7 | 8 | An [Arduino](https://arduino.cc/) library for sending and receiving data using [Cirrus logic CS5530](https://www.lora-alliance.org/) . 9 | 10 | ## Compatible Hardware 11 | 12 | * [CS5530](https://www.cirrus.com/products/cs5530/) based boards including: 13 | * [CS5530 Shield v1.0](https://www.aliexpress.com/item/1005002054335619.html) 14 | * [CS5530 Sheild v2.0](https://www.aliexpress.com/item/1005002394037116.html) 15 | 16 | 17 | ### Cirrus logic CS5530 wiring 18 | 19 | | Cirrus logic CS5530 | Arduino | 20 | | :---------------------: | :------:| 21 | | VCC | 5.0V | 22 | | GND | GND | 23 | | SCK | SCK | 24 | | SDO | MISO | 25 | | SDI | MOSI | 26 | | NSS | 10 | 27 | 28 | 29 | `NSS` pin can be changed by using `cell.setPin(ss)`. 30 | 31 | **NOTES**: 32 | * Some boards (like the Arduino Nano), cannot supply enough current for the CS5530 in TX mode. This will cause lockups when sending, be sure to use an external 3.3V supply that can provide at least 120mA's when using these boards. 33 | * If your Arduino board operates at 5V or 3.3V, no need to use a level converter for the wiring to the Cirrus logic CS5530 module. 34 | 35 | ## Installation 36 | 37 | ### Using the Arduino IDE Library Manager 38 | 39 | 1. Choose `Sketch` -> `Include Library` -> `Manage Libraries...` 40 | 2. Type `CS5530` into the search box. 41 | 3. Click the row to select the library. 42 | 4. Click the `Install` button to install the library.. 43 | 44 | ### Using Git 45 | 46 | ```sh 47 | cd ~/Documents/Arduino/libraries/ 48 | git clone https://github.com/yasir-shahzad/CS5530 49 | ``` 50 | 51 | ## API 52 | 53 | See [API.md](API.md). 54 | 55 | ## Examples 56 | 57 | See [examples](examples) folder. 58 | 59 | ## FAQ 60 | 61 | **1) Initializing the CS5530 is failing** 62 | 63 | Please check the wiring you are using matches what's listed in [Cirrus logic CS5530](# Cirrus logic CS5530-wiring). You can also use `cell.setPins(ss)` to change the default pins used. You can call `cell.setSPIFrequency(frequency)` to lower the SPI frequency used by the library. Both API's must be called before `cell.begin(...)`. 64 | 65 | **2) Is CS5530 MSBFIRST or LSBFIRST?** 66 | 67 | If we see in the data sheet we can clearly see the CS5530 is MSBFIRST. 68 | 69 | **3) Which SPI mode does CS5530 uses?** 70 | 71 | if we see at Cpoles and Cphases in data-sheet, we can clearly analize from graphs that it's SPI_MODE0. 72 | 73 | **4) Does it SPI works on fixed frequency?** 74 | 75 | No, It's SPI work on different frequency ranges. 76 | 77 | **5) Can this library be used for CS5532 or CS5534?** 78 | 79 | Yes, It's SPI communication works on all the cirrus logic chips. But you have to change register configurations. 80 | 81 | ## License 82 | 83 | This libary is [licensed](LICENSE) under the [MIT Licence](https://en.wikipedia.org/wiki/MIT_License). 84 | -------------------------------------------------------------------------------- /doc/CS5530-Module-24-bit-ADC.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasir-shahzad/CS5530_ADC_Arduino_Library/7087e1882ea2371d3b123dd200c2c54695a3cb41/doc/CS5530-Module-24-bit-ADC.jpg -------------------------------------------------------------------------------- /doc/CS5530.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yasir-shahzad/CS5530_ADC_Arduino_Library/7087e1882ea2371d3b123dd200c2c54695a3cb41/doc/CS5530.pdf -------------------------------------------------------------------------------- /examples/CS5530_basic/CS5530_basic.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Connections: 3 | Arduino NANO/Uno vCS5530 Description 4 | (ATMEGA 328P) 24bit ADC 5 | 6 | D2 (GPIO4) 0 RST Output from ESP to reset display 7 | D1 (GPIO5) 1 CE Output from ESP to chip select/enable display 8 | D6 (GPIO12) 2 DC Output from display data/command to ESP 9 | D7 (GPIO13) 3 Din Output from ESP SPI MOSI to display data input 10 | D5 (GPIO14) 4 Clk Output from ESP SPI clock 11 | 3V3 5 Vcc 3.3V from ESP to display 12 | D0 (GPIO16) 6 BL 3.3V to turn backlight on, or PWM 13 | G 7 Gnd Ground 14 | 15 | Dependencies: 16 | https://github.com/yasir-shahzad/CS5530 17 | 18 | */ 19 | 20 | #include "Arduino.h" 21 | 22 | #include 23 | #include "SPI.h" 24 | #include 25 | 26 | CS5530 cell; 27 | 28 | uint32_t startTime; 29 | int32_t value; 30 | 31 | void setup() 32 | { 33 | Serial.begin(115200); 34 | 35 | if (cell.reset()) 36 | Serial.println("CS5530 Initialized Successfully"); 37 | else { 38 | Serial.println("CS5530 Initialization Failed"); 39 | while (1); 40 | } 41 | 42 | 43 | // cell.CS5530_Write_Reg(CMD_GAIN_WRITE, 0x3); 44 | 45 | // uint32_t tmp = cell.getRegister(Command::ConfigRead); 46 | uint32_t tmp = cell.getRegister(static_cast(Command::ConfigRead)); 47 | 48 | Serial.print("CONFIG Register:"); 49 | Serial.println(tmp, BIN); 50 | 51 | // uint32_t tmpdata = REG_CONFIG_UNIPOLAR | REG 52 | 53 | cell.setRegister(static_cast(Command::ConfigWrite), CS5530_UNIPOLAR); 54 | 55 | // cell.convert(CONTINUED_CONVERSION, 1, 1, (int)WORD_RATE_3200SPS); 56 | 57 | uint32_t cmpl = cell.calculateTwoComplement(0xFFFFFFFF); 58 | 59 | //cell.writeByte(ContinuousConversion); 60 | cell.setRegister(OffsetWrite, cmpl); 61 | } 62 | 63 | void loop() 64 | { 65 | int32_t recData = cell.getReading(); 66 | 67 | Serial.println(recData); 68 | if (recData > 0) 69 | { 70 | value = 0.97 * value + 0.03 * recData; // running average 71 | Serial.println(value); 72 | // delay(5); 73 | } 74 | 75 | if (millis() > startTime) 76 | { 77 | 78 | // Serial.println (String((value-111683)/18) + " grms"); 79 | startTime = millis() + 200; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /examples/CS5530_setFrequency/CS5530_setFrequency.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Connections: 3 | Arduino NANO/Uno vCS5530 Description 4 | (ATMEGA 328P) 24bit ADC 5 | 6 | D2 (GPIO4) 0 RST Output from ESP to reset display 7 | D1 (GPIO5) 1 CE Output from ESP to chip select/enable display 8 | D6 (GPIO12) 2 DC Output from display data/command to ESP 9 | D7 (GPIO13) 3 Din Output from ESP SPI MOSI to display data input 10 | D5 (GPIO14) 4 Clk Output from ESP SPI clock 11 | 3V3 5 Vcc 3.3V from ESP to display 12 | D0 (GPIO16) 6 BL 3.3V to turn backlight on, or PWM 13 | G 7 Gnd Ground 14 | 15 | Dependencies: 16 | https://github.com/yasir-shahzad/CS5530 17 | 18 | */ 19 | 20 | 21 | #include "Arduino.h" 22 | 23 | #include 24 | #include "SPI.h" 25 | #include "CS5530.h" 26 | 27 | 28 | 29 | CS5530 cell; 30 | 31 | void setup() { 32 | Serial.begin(115200); 33 | 34 | 35 | 36 | if (cell.reset()) 37 | Serial.println("CS5530 Initialized Successfully"); 38 | else 39 | Serial.println("Starting CS5530 failed"); 40 | 41 | // cell.CS5530_Write_Reg(CMD_GAIN_WRITE, 0x3); 42 | 43 | uint32_t tmp = cell.getRegister( ConfigRead 44 | ); 45 | Serial.print("CONFIG Register:"); 46 | Serial.println(tmp, BIN); 47 | 48 | //uint32_t tmpdata = REG_CONFIG_UNIPOLAR | REG 49 | 50 | cell.setRegister(ConfigWrite, CS5530_UNIPOLAR); 51 | 52 | 53 | //cell.Convert(CONTINUED_CONVERSION, 1, 1, (int)WORD_RATE_3200SPS ); 54 | 55 | uint32_t cmpl = cell.calculateTwoComplement(0xFFFFFFFF); 56 | 57 | 58 | cell.writeByte(CMD_CONVERSION_CONTINU); 59 | cell.setRegister(CMD_OFFSET_WRITE, cmpl); 60 | 61 | 62 | } 63 | 64 | 65 | void loop() { 66 | int32_t recData = cell.getReading(); 67 | 68 | if(recData > 0) { 69 | 70 | value = 0.97 * value + 0.03 * recData; // running average 71 | delay(5); 72 | } 73 | 74 | if(millis() > startTime){ 75 | Serial.println (String((value-111683)/18) + " grms"); 76 | 77 | startTime = millis()+200; 78 | } 79 | 80 | } 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For LoRa 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | LoRa KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | begin KEYWORD2 16 | end KEYWORD2 17 | 18 | beginPacket KEYWORD2 19 | endPacket KEYWORD2 20 | 21 | parsePacket KEYWORD2 22 | packetRssi KEYWORD2 23 | packetSnr KEYWORD2 24 | packetFrequencyError KEYWORD2 25 | 26 | rssi KEYWORD2 27 | 28 | write KEYWORD2 29 | 30 | available KEYWORD2 31 | read KEYWORD2 32 | peek KEYWORD2 33 | flush KEYWORD2 34 | 35 | onReceive KEYWORD2 36 | onTxDone KEYWORD2 37 | receive KEYWORD2 38 | idle KEYWORD2 39 | sleep KEYWORD2 40 | 41 | setTxPower KEYWORD2 42 | setFrequency KEYWORD2 43 | setSpreadingFactor KEYWORD2 44 | setSignalBandwidth KEYWORD2 45 | setCodingRate4 KEYWORD2 46 | setPreambleLength KEYWORD2 47 | setSyncWord KEYWORD2 48 | enableCrc KEYWORD2 49 | disableCrc KEYWORD2 50 | enableInvertIQ KEYWORD2 51 | disableInvertIQ KEYWORD2 52 | setGain KEYWORD2 53 | 54 | random KEYWORD2 55 | setPins KEYWORD2 56 | setSPIFrequency KEYWORD2 57 | dumpRegisters KEYWORD2 58 | 59 | ####################################### 60 | # Constants (LITERAL1) 61 | ####################################### 62 | 63 | PA_OUTPUT_RFO_PIN LITERAL1 64 | PA_OUTPUT_PA_BOOST_PIN LITERAL1 65 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=CS5530 2 | version=0.8.0 3 | author=Yasir Shahzad 4 | maintainer=Yasir Shahzad 5 | sentence=An Arduino library for CS5530 based weight scales. 6 | paragraph=Supports CIRRUS LOGGIC CS5530 based boards/shields. 7 | category=sensors 8 | url=https://github.com/yasir-shahzad/CS5530 9 | architectures=* 10 | includes=CS5530.h 11 | -------------------------------------------------------------------------------- /src/CS5530.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "CS5530.h" 5 | #include "Arduino.h" 6 | #include 7 | 8 | 9 | CS5530::CS5530(): 10 | _spiSettings(CS5530_DEFAULT_SPI_FREQUENCY, MSBFIRST, SPI_MODE0), 11 | _spi(&CS5530_DEFAULT_SPI), _chipSelectPin(CS5530_SS) 12 | { 13 | _spi->begin(); 14 | } 15 | 16 | int CS5530::begin() 17 | { 18 | pinMode(_chipSelectPin, OUTPUT); 19 | digitalWrite(_chipSelectPin, HIGH); 20 | _spi->begin(); 21 | 22 | return 1; 23 | } 24 | 25 | void CS5530::setPin(int ss) 26 | { 27 | _chipSelectPin = ss; 28 | } 29 | 30 | void CS5530::setSPI(SPIClass &spi) 31 | { 32 | _spi = &spi; 33 | } 34 | 35 | void CS5530::setSPIFrequency(uint32_t frequency) 36 | { 37 | _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0); 38 | } 39 | 40 | bool CS5530::reset(void) 41 | { 42 | int i; 43 | uint32_t tmp; 44 | 45 | // Initilizing SPI port 46 | for (i = 0; i < 15; i++) { 47 | writeByte(Sync1); 48 | } 49 | writeByte(Sync0); 50 | // Reseting CS5530 51 | setRegister(ConfigWrite, SYSTEM_RESET); 52 | delay(1); // Wait 1 milli seconds 53 | setRegister(ConfigWrite, Null); 54 | 55 | tmp = getRegister(ConfigRead); 56 | //valid reset will set RV to 1 57 | if (tmp & RESET_VALID) { 58 | return true; 59 | } 60 | 61 | return false; 62 | } 63 | 64 | 65 | //Set the gain 66 | //x1, 2, 4, 8, 16, 32, 64 are avaialable 67 | bool CS5530::setGain(uint8_t gainValue) 68 | { 69 | if (gainValue > 1 << 6) 70 | gainValue = 1 << 6; // Error check 71 | 72 | uint32_t value = getRegister(GainRead); 73 | // Clear gain bits (bits 12, 13, 14, and 15) 74 | value &= ~(0b1111 << 12); 75 | // Mask in new bits 76 | value |= (static_cast(gainValue) << 12); 77 | 78 | // Return true to indicate success 79 | return (setRegister(GainWrite, value)); 80 | } 81 | 82 | //Set the readings per second 83 | //10, 20, 40, 80, and 320 samples per second is available 84 | bool CS5530::setSampleRate(uint32_t rate) 85 | { 86 | if (rate > 0b111) 87 | rate = 0b111; //Error check 88 | 89 | uint32_t value = getRegister(ConfigRead); 90 | value &= 0b10001111; //Clear CRS bits 91 | value |= rate << 11; //Mask in new CRS bits 92 | 93 | return (setRegister(ConfigWrite, value)); 94 | } 95 | 96 | //Call when scale is setup, level, at running temperature, with nothing on it 97 | void CS5530::calculateZeroOffset(uint8_t averageAmount) 98 | { 99 | setZeroOffset(getAverage(averageAmount)); 100 | } 101 | 102 | //Sets the internal variable. Useful for users who are loading values from NVM. 103 | void CS5530::setZeroOffset(int32_t newZeroOffset) 104 | { 105 | _zeroOffset = newZeroOffset; 106 | } 107 | 108 | int32_t CS5530::getZeroOffset() 109 | { 110 | return (_zeroOffset); 111 | } 112 | 113 | //Call after zeroing. Provide the float weight sitting on scale. Units do not matter. 114 | void CS5530::calculateCalibrationFactor(float weightOnScale, uint8_t averageAmount) 115 | { 116 | int32_t onScale = getAverage(averageAmount); 117 | float newCalFactor = (onScale - _zeroOffset) / (float)weightOnScale; 118 | setCalibrationFactor(newCalFactor); 119 | } 120 | 121 | //Pass a known calibration factor into library. Helpful if users is loading settings from NVM. 122 | //If you don't know your cal factor, call setZeroOffset(), then calculateCalibrationFactor() with a known weight 123 | void CS5530::setCalibrationFactor(float newCalFactor) 124 | { 125 | _calibrationFactor = newCalFactor; 126 | } 127 | 128 | float CS5530::getCalibrationFactor() 129 | { 130 | return (_calibrationFactor); 131 | } 132 | 133 | 134 | //Returns the y of y = mx + b using the current weight on scale, the cal factor, and the offset. 135 | float CS5530::getWeight(bool allowNegativeWeights, uint8_t samplesToTake) 136 | { 137 | int32_t onScale = getAverage(samplesToTake); 138 | 139 | //Prevent the current reading from being less than zero offset 140 | //This happens when the scale is zero'd, unloaded, and the load cell reports a value slightly less than zero value 141 | //causing the weight to be negative or jump to millions of pounds 142 | if (allowNegativeWeights == false) 143 | { 144 | if (onScale < _zeroOffset) 145 | onScale = _zeroOffset; //Force reading to zero 146 | } 147 | 148 | float weight = (onScale - _zeroOffset) / _calibrationFactor; 149 | return (weight); 150 | } 151 | 152 | bool CS5530::setRegister(uint8_t command, uint32_t value) 153 | { 154 | writeByte(command); 155 | write32(value); 156 | return true; 157 | } 158 | 159 | // void CS5530::setBit(uint8_t reg, uint32_t dat) { 160 | // uint32_t tmp = 0; 161 | // uint8_t cmd = 0; 162 | // switch (reg) 163 | // { 164 | // case CMD_GAIN_WRITE: cmd = CMD_GAIN_READ; break; 165 | // case CMD_OFFSET_WRITE: cmd = CMD_OFFSET_READ; break; 166 | // case ConfigWrite: cmd = ConfigRead 167 | // ; break; 168 | // } 169 | 170 | // tmp = getRegister(cmd); 171 | // tmp |= dat; 172 | // writeByte(reg); 173 | // write32(tmp); 174 | // } 175 | 176 | 177 | //Mask & set a given bit within a register 178 | bool CS5530::setBit(uint8_t bitNumber, uint8_t registerAddress) 179 | { 180 | uint32_t value = getRegister(registerAddress); 181 | value |= (1 << bitNumber); //Set this bit 182 | return (setRegister(registerAddress, value)); 183 | } 184 | 185 | //Mask & clear a given bit within a register 186 | bool CS5530::clearBit(uint8_t bitNumber, uint8_t registerAddress) 187 | { 188 | uint32_t value = getRegister(registerAddress); 189 | value &= ~(1 << bitNumber); //Set this bit 190 | return (setRegister(registerAddress, value)); 191 | } 192 | 193 | //Return a given bit within a register 194 | bool CS5530::getBit(uint8_t bitNumber, uint8_t registerAddress) 195 | { 196 | uint32_t value = getRegister(registerAddress); 197 | value &= (1 << bitNumber); //Clear all but this bit 198 | return (value); 199 | } 200 | 201 | // void CS5530::resetBit(uint8_t reg, uint32_t dat) 202 | // { 203 | // uint32_t tmp = 0; 204 | // uint8_t cmd = 0; 205 | // switch (reg) 206 | // { 207 | // case CMD_GAIN_WRITE: 208 | // cmd = CMD_GAIN_READ; 209 | // break; 210 | // case CMD_OFFSET_WRITE: 211 | // cmd = CMD_OFFSET_READ; 212 | // break; 213 | // case ConfigWrite: 214 | // cmd = ConfigRead 215 | // ; 216 | // break; 217 | // } 218 | 219 | // tmp = getRegister(cmd); 220 | // tmp &= ~dat; 221 | // writeByte(reg); 222 | // write32(tmp); 223 | // } 224 | 225 | void CS5530::writeByte(uint8_t data) { 226 | digitalWrite(_chipSelectPin, LOW); 227 | _spi->beginTransaction(_spiSettings); 228 | _spi->transfer(data & 0xFF); 229 | _spi->endTransaction(); 230 | digitalWrite(_chipSelectPin, HIGH); 231 | } 232 | 233 | void CS5530::write32(uint32_t dat) 234 | { 235 | for (int8_t i = 3; i >= 0; i--) { 236 | writeByte(static_cast((dat >> (8 * i)) & 0xFF)); 237 | } 238 | } 239 | 240 | uint32_t CS5530::getRegister(uint8_t command) { 241 | writeByte(command); 242 | return read32(); 243 | } 244 | 245 | uint32_t CS5530::read32(void) { 246 | uint32_t result = 0; 247 | 248 | for (int i = 0; i < 4; i++) { 249 | result = (result << 8) | readByte(); 250 | } 251 | 252 | return result; 253 | } 254 | 255 | uint8_t CS5530::readByte() { 256 | uint8_t data = 0; 257 | 258 | _spi->beginTransaction(_spiSettings); 259 | digitalWrite(_chipSelectPin, LOW); 260 | data = _spi->transfer(Null); 261 | digitalWrite(_chipSelectPin, HIGH); 262 | _spi->endTransaction(); 263 | 264 | return data; 265 | } 266 | 267 | bool CS5530::available(void) 268 | { 269 | if(digitalRead(12) == 0) 270 | return true; 271 | 272 | return false; 273 | } 274 | 275 | int32_t CS5530::getReading() 276 | { 277 | if (!available()) 278 | return -2; // Return -2 for busy status 279 | 280 | uint32_t recData = getRegister(Null); 281 | if ((recData & REG_DATA_OF) == 0) { 282 | // Perform sign extension and return the result 283 | return static_cast(recData << 24) >> 24; 284 | } else { 285 | // Return -1 for overflow status 286 | return -1; 287 | } 288 | } 289 | 290 | //Return the average of a given number of readings 291 | //Gives up after 1000ms so don't call this function to average 8 samples setup at 1Hz output (requires 8s) 292 | int32_t CS5530::getAverage(uint8_t averageAmount) 293 | { 294 | long total = 0; 295 | uint8_t samplesAquired = 0; 296 | 297 | unsigned long startTime = millis(); 298 | while (1) 299 | { 300 | if (available() == true) 301 | { 302 | total += getReading(); 303 | if (++samplesAquired == averageAmount) 304 | break; //All done 305 | } 306 | if (millis() - startTime > 1000) 307 | return (0); //Timeout - Bail with error 308 | delay(1); 309 | } 310 | total /= averageAmount; 311 | 312 | return (total); 313 | } 314 | 315 | uint8_t CS5530::calibrate(uint8_t calibrateType, int cfgReg) 316 | { 317 | uint32_t calibrateResult; 318 | cfgReg = (int)((calibrateType % 2 == 1) ? (cfgReg | INPUT_SHORT) : (cfgReg)); 319 | uint8_t cmd, readReg; 320 | 321 | switch (calibrateType) 322 | { 323 | case SYSTEM_OFFSET: 324 | cmd = SystemOffsetCalib; 325 | readReg = OffsetRead; 326 | break; 327 | case SYSTEM_GAIN: 328 | cmd = SystemGainCalib; 329 | readReg = GainRead; 330 | break; 331 | } 332 | 333 | setRegister(ConfigWrite, cfgReg); 334 | writeByte(cmd); 335 | 336 | delayMicroseconds(10); // waste some time 337 | 338 | calibrateResult = getRegister(readReg); 339 | printf("The calibration result is: %x\n", calibrateResult); 340 | 341 | return 1; 342 | } 343 | 344 | 345 | uint32_t CS5530::calculateTwoComplement(uint32_t value) 346 | { 347 | uint32_t isNegative = (value & (1UL << 23)) != 0; 348 | uint32_t result; 349 | 350 | if (isNegative) 351 | result = value | ~((1UL << 24) - 1); 352 | else 353 | result = value; 354 | 355 | return result; 356 | } 357 | 358 | 359 | uint8_t CS5530::convert(uint8_t convertType, uint8_t regNo, int wordRate) 360 | { 361 | uint32_t finalResult = 0; 362 | uint32_t cfgReg = (uint32_t)VOLTAGE_REF_SELECT; 363 | uint8_t cmd; 364 | 365 | switch (convertType) 366 | { 367 | case SINGLE_CONVERSION: 368 | cmd = SingleConversion; 369 | break; 370 | case CONTINUED_CONVERSION: 371 | cmd = ContinuousConversion; 372 | break; 373 | } 374 | 375 | setRegister(ConfigWrite, cfgReg); 376 | writeByte(cmd); 377 | printf("Conversion begins...\n"); 378 | 379 | delayMicroseconds(10); // waste some time 380 | u8 test = 0; 381 | // readByte(&test, 1); 382 | // readByte(convertResult, 4); 383 | 384 | Serial.print("The raw result is:"); 385 | Serial.println(finalResult, BIN); 386 | Serial.print("The raw result is:"); 387 | Serial.println(finalResult); 388 | 389 | finalResult = calculateTwoComplement(finalResult); 390 | Serial.print("The final result is:"); 391 | Serial.println(finalResult, BIN); 392 | Serial.print("The final result is:"); 393 | Serial.println(finalResult); 394 | 395 | finalResult = finalResult * 500 / 0x7fffff; 396 | Serial.print("The final result is:"); 397 | Serial.println(finalResult); 398 | 399 | return 1; 400 | } 401 | 402 | -------------------------------------------------------------------------------- /src/CS5530.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 by Yasir Shahzad 3 | * 4 | * This file is free software; you can redistribute it and/or modify 5 | * it under the terms of either the GNU General Public License version 2 6 | * or the GNU Lesser General Public License version 2.1, both as 7 | * published by the Free Software Foundation. 8 | */ 9 | 10 | 11 | #ifndef CS5530_H 12 | #define CS5530_H 13 | 14 | #include 15 | 16 | 17 | #define SYSTEM_OFFSET 3 18 | #define SYSTEM_GAIN 4 19 | 20 | typedef enum { 21 | SINGLE_CONVERSION = 1, 22 | CONTINUED_CONVERSION = 2 23 | } Conversion_Type; 24 | 25 | //Alias of Basic Results 26 | #define PASS 0x0 27 | #define FAIL 0xff 28 | #define TRUE 1 29 | #define FALSE 0 30 | 31 | #define NOTHING 0 32 | #define CS5530_READ_DATA_TIMEOUT 2000000 33 | #define TIMEOUTERR 0xff 34 | #define SUCCESSFUL 0x0 35 | #define CMD_STOP_CONT_CONV 0xff 36 | #define CAL_TIMEOUT_LIMIT 4000 37 | #define READ_CONV_RESULT 0x00 38 | 39 | #define DATA_VALID 0 40 | #define ERR_AD_BUSY 1 41 | #define ERR_AD_OVER_FLOW 2 42 | #define ERR_FILTER_ONGOING 3 43 | 44 | 45 | /** 46 | * @brief Enumeration of commands that can be sent to the Tic stepper motor controller. 47 | * 48 | * These commands are used to set and retrieve various settings and parameters of the Tic controller. 49 | * 50 | * @note This enumeration is based on the Tic Stepper Motor Controller User's Guide, available at 51 | * 52 | */ 53 | typedef enum 54 | { 55 | OffsetRead = 0x09, ///< Read the offset value. 56 | OffsetWrite = 0x01, ///< Write the offset value. 57 | GainRead = 0x0A, ///< Read the gain value. 58 | GainWrite = 0x02, ///< Write the gain value. 59 | ConfigRead = 0x0B, ///< Read the configuration value. 60 | ConfigWrite = 0x03, ///< Write the configuration value. 61 | SingleConversion = 0x80, ///< Perform a single conversion. 62 | ContinuousConversion= 0xC0, ///< Perform continuous conversions. 63 | SystemOffsetCalib = 0x85, ///< System offset calibration. 64 | SystemGainCalib = 0x86, ///< System gain calibration. 65 | Sync1 = 0xFF, ///< Part of the serial port re-initialization sequence. 66 | Sync0 = 0xFE, ///< End of the serial port re-initialization sequence. 67 | Null = 0x00 ///< Clear a port flag and keep the converter in continuous conversion mode. 68 | } Command; 69 | 70 | typedef enum 71 | { 72 | CS5530_GAIN_64 = 1 << 6, ///< Gain: 64 73 | CS5530_GAIN_32 = 1 << 5, ///< Gain: 32 74 | CS5530_GAIN_16 = 1 << 4, ///< Gain: 16 75 | CS5530_GAIN_8 = 1 << 3, ///< Gain: 8 76 | CS5530_GAIN_4 = 1 << 2, ///< Gain: 4 77 | CS5530_GAIN_2 = 1 << 1, ///< Gain: 2 78 | CS5530_GAIN_1 = 1 << 0 ///< Gain: 1 79 | } CS5530_Gain_Values; 80 | 81 | 82 | typedef enum 83 | { 84 | CS5530_SPS_3200 = 0b1000, ///< 3200 SPS 85 | CS5530_SPS_1600 = 0b1001, ///< 1600 SPS 86 | CS5530_SPS_800 = 0b1010, ///< 800 SPS 87 | CS5530_SPS_400 = 0b1011, ///< 400 SPS 88 | CS5530_SPS_200 = 0b1100, ///< 200 SPS 89 | CS5530_SPS_100 = 0b0000, ///< 100 SPS 90 | CS5530_SPS_50 = 0b0001, ///< 50 SPS 91 | CS5530_SPS_25 = 0b0010, ///< 25 SPS 92 | CS5530_SPS_12P5 = 0b0011, ///< 12.5 SPS 93 | CS5530_SPS_6P25 = 0b0100, ///< 6.25 SPS 94 | } CS5530_SPS_Values; 95 | 96 | typedef enum { 97 | PWR_SAVE_SELECT = 1UL << 31, ///< Power Save Select 98 | POWER_DOWN_MODE = 1UL << 30, ///< Power Down Mode 99 | SYSTEM_RESET = 1UL << 29, ///< Reset System 100 | RESET_VALID = 1UL << 28, ///< Reset Valid 101 | INPUT_SHORT = 1UL << 27, ///< Input Short 102 | VOLTAGE_REF_SELECT = 1UL << 25, ///< Voltage Reference Select 103 | A1_CONFIGURATION = 1UL << 24, ///< A1 Configuration 104 | A0_CONFIGURATION = 1UL << 23, ///< A0 Configuration 105 | FILTER_RATE_SELECT = 1UL << 19, ///< Filter Rate Select 106 | OPEN_CIRCUIT_DETECT = 1UL << 9 ///< Open Circuit Detect 107 | } RegisterConfig; 108 | 109 | 110 | //Unipolar / Bipolar 111 | #define CS5530_UNIPOLAR 1UL << 10 112 | #define CS5530_BIPOLAR 0UL << 10 113 | #define REG_DATA_OF 1UL << 3 114 | 115 | #define CMD_STOP_CONT_CONV 0xFF 116 | 117 | #define CS5530_DEFAULT_SPI SPI 118 | #define CS5530_DEFAULT_SPI_FREQUENCY 8E6 119 | #define CS5530_SS 10 120 | 121 | 122 | 123 | enum EAdStatus { 124 | E_AD_STATUS_BUSY, 125 | E_AD_STATUS_READY, 126 | E_AD_STATUS_OVERFLOW 127 | }; 128 | 129 | class CS5530 130 | { 131 | public: 132 | CS5530(); 133 | int begin(); 134 | void setPin(int ss = CS5530_SS); 135 | void setSPI(SPIClass &spi); 136 | void setSPIFrequency(uint32_t value); 137 | uint32_t calculateTwoComplement(uint32_t value); 138 | bool isConnected(); //Returns true if device acks at the I2C address 139 | 140 | bool available(); //Returns true if Cycle Ready bit is set (conversion is complete) 141 | int32_t getReading(); //Returns 24-bit reading. Assumes CR Cycle Ready bit (ADC conversion complete) has been checked by .available() 142 | int32_t getAverage(uint8_t samplesToTake); //Return the average of a given number of readings 143 | 144 | void calculateZeroOffset(uint8_t averageAmount = 8); //Also called taring. Call this with nothing on the scale 145 | void setZeroOffset(int32_t newZeroOffset); //Sets the internal variable. Useful for users who are loading values from NVM. 146 | int32_t getZeroOffset(); //Ask library for this value. Useful for storing value into NVM. 147 | 148 | void calculateCalibrationFactor(float weightOnScale, uint8_t averageAmount = 8); //Call this with the value of the thing on the scale. Sets the calibration factor based on the weight on scale and zero offset. 149 | void setCalibrationFactor(float calFactor); //Pass a known calibration factor into library. Helpful if users is loading settings from NVM. 150 | float getCalibrationFactor(); //Ask library for this value. Useful for storing value into NVM. 151 | 152 | float getWeight(bool allowNegativeWeights = false, uint8_t samplesToTake = 8); //Once you've set zero offset and cal factor, you can ask the library to do the calculations for you. 153 | 154 | bool setGain(uint8_t gainValue); // Set the gain. x1, 2, 4, 8, 16, 32, 64, 128 are available 155 | bool setSampleRate(uint32_t rate); // Set the readings per second. 10, 20, 40, 80, and 320 samples per second is available 156 | 157 | uint32_t getRegister(uint8_t commnad); //Get contents of a register 158 | bool setRegister(uint8_t command, uint32_t value); //Send a given value to be written to given address. Return true if successful 159 | 160 | uint8_t convert(uint8_t convertType, uint8_t regNo, int wordRate); 161 | uint8_t calibrate(uint8_t calibrateType, int cfgReg); 162 | 163 | bool setBit(uint8_t bitNumber, uint8_t registerAddress); //Mask & set a given bit within a register 164 | bool clearBit(uint8_t bitNumber, uint8_t registerAddress); //Mask & clear a given bit within a register 165 | bool getBit(uint8_t bitNumber, uint8_t registerAddress); //Return a given bit within a register 166 | 167 | bool reset(); //Resets all registers to Power Of Defaults 168 | 169 | private: 170 | SPISettings _spiSettings; 171 | SPIClass* _spi; 172 | int _chipSelectPin; 173 | //y = mx+b 174 | int32_t _zeroOffset; //This is b 175 | float _calibrationFactor; //This is m. User provides this number so that we can output y when requested 176 | 177 | uint8_t readByte(); 178 | uint32_t read32(); 179 | void write32(uint32_t value); 180 | void writeByte(uint8_t value); 181 | 182 | 183 | }; 184 | 185 | #endif 186 | 187 | 188 | 189 | 190 | --------------------------------------------------------------------------------