AS3935 lightning and TCS3471x color/light sensor libraries

Thought I might share libraries I made for these chips, AS3935 lightning detector chip (yes, lightning) and TCS34711, TCS34713, TCS34715 and TCS34717 color and light sensor chips, by coincidence both by www.ams.com.

AS3935 is fun little chip that detects lightnings up to 40km afar, since it uses ferrite rod antenna it is somewhat directional, but anyway, it does what it says, detects lightnings. Library using SPI communications - GitHub - raivisr/AS3935-Arduino-Library: AS3935 Franklin Lightning Sensor™ IC by AMS Arduino library, I made this library so that it does not depend on specific implementation of SPI, so one can use bitbanged SPI, hardware SPI or whatever SPI.

TCS3471 series of color/light sensors are highly sensitive and have 16bit resolution, they use i2c interface. Library I wrote - GitHub - raivisr/TCS3471-Arduino-Library: TCS3471 Color and light sensor IC by AMS Arduino library. This library is written so that library code does not access Wire library directly, but rather requires user sketch to provide functions to send and receive data over i2c bus. I did that for a couple of reasons, one reason is that TCS3471 series of chips have fixed i2c address, another reason, I wanted to make the code usable on most of Arduinos and Arduino compatible platforms and the third reason, this way user can use i2c multiplexer to address multiple chips and library requires no changes to accommodate for that.
According to TCS3471 datasheet, these chips are pin and register compatible with all TCS3x7x chips, but I have tested the library only with TCS34717.

Breakouts for these two, if anyone is interested, can be found here - https://www.tindie.com/shops/TAUTIC/

Thanks for sharing!
+1

I like lightning, maybe I buy such sensor;)

had a quick look at the lightning lib, decent piece of work

two remarks

  • you can extract writeSPI as it is used a few times.
// private
void _writeSPI(byte val1, byte val2)
{
  digitalWrite(_CSPin,LOW);
  SPITransferFunc(val1);
  SPITransferFunc(val2);
  digitalWrite(_CSPin,HIGH);
}

and in the constructor

AS3935::AS3935(byte (*SPItransfer)(byte),int csPin, int irq)
{
	SPITransferFunc = SPItransfer;
	_CSPin = csPin;
	_IRQPin = irq;

	digitalWrite(_CSPin,HIGH);
	pinMode(_CSPin,OUTPUT);
	pinMode(_IRQPin,INPUT);
}

swapping the lines this way will prevent a possible (very) short LOW on the _CSPin . It was mentioned in another discussion not so long ago.

first issue, well, not sure it would do any good or bad to the size of binary (although, i might check that), otherwise there is no reason to change, as nobody looks at the code of libraries most of the time :slight_smile:
second, duly noted and pushed to git, thank you.

The TCS3471 lib looks also like some decent work, but I have a more serious remark here.

In the color library I would remove detect() and all tests to _detected. The _detected constructs makes the library definitely more robust I know.
But more importantly (imho) you cannot have two of these sensors on the bus any more. Most libs give the address as parameter to the constructor.

The footprint of the lib would be smaller (to be tested how much) too.

Still good work!

first issue, well, not sure it would do any good or bad to the size of binary (although, i might check that) otherwise there is no reason to change

Agree, but especially on the UNO all bytes saved (even a few) add up and frees memory for other functionality.
Please let me know the diff in size (esp for the color lib)

as nobody looks at the code of libraries most of the time

I do if the sensors / topic interests me :wink:

All that said, I must say you delivered well written code and again thanks for sharing.

robtillaart:
The TCS3471 lib looks also like some decent work, but I have a more serious remark here.

In the color library I would remove detect() and all tests to _detected. The _detected constructs makes the library definitely more robust I know.
But more importantly (imho) you cannot have two of these sensors on the bus any more. Most libs give the address as parameter to the constructor.

The footprint of the lib would be smaller (to be tested how much) too.

Still good work!

The library was written with this board in mind https://tindie.com/shops/TAUTIC/tcs34717-color-sensor-breakout/, which has TXS0104 level converter chip on it, outputs of which can be put in high impedance state, so in theory (not tested yet), one could attach more than one chip to i2c, make multiple instances of TCS3471 object and take care of addressing specific instance in sketch, or one could use i2c multiplexer like TCA9548A and again use multiple instances of TCS3471. Besides, each instance tries to determine correct address on it's own, since different versions of chip can have either address 0x29 or 0x39. If Arduino environment follows regular c++ rules, which I hope it does, since compiler is based on gcc, each instance will have it's own copy of member variables, since none of them is declared as static.
Nevertheless, I might consider reviewing the code if there is enough interest in this, besides this is version 1. Much more footprint could be saved if I got rid of float arguments to some functions, but I decided to leave those in for ease of use :slight_smile:

Thanks for review :slight_smile:

Besides, each instance tries to determine correct address on it's own, since different versions of chip can have either address 0x29 or 0x39.

But I foresee this scenario:

object1 will test address1 first and find it on the I2C bus => happy
object2 will test address1 first and find it on the I2C bus => happy (oops)

I saw the floating point and yes you can save quite a bit there.
You could use an uint16_t and set the timing in milliseconds to get the 1/10 of second behavior identical.
That would allow for periods up to 65 seconds (if it indicates millis).

If you use an uint16_t for 1/10 of second you can even do longer timings.

Eager to see the size improvements you will get!

User sketch has to take care of defining different sets of communication functions for each of instances, that way one can ensure that right chip is addressed in case of multiplexer or right chip is enabled in case of level shifter.
I left those floats in because milliseconds are less confusing than 10x milliseconds. Allowed values are limited by chip itself, for one of timing functions it is 2.4ms-614.4ms, but for another one it is 2.4-7372.8ms, which translates to uint32_t if 10x the value is used. Anyway, if that becomes a problem, I will re-consider these things.

Still trying to compile this code for my Arduino Mega 256. Just downloaded the chip library and new copy of Arduino.

AS3935\AS3935.cpp.o: In function AS3935::_ffsz(unsigned char)': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:49: multiple definition of AS3935::_ffsz(unsigned char)'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:49: first defined here
c:/users/office/desktop/arduino-1.0.4/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions
AS3935\AS3935.cpp.o: In function AS3935::_SPITransfer2(unsigned char, unsigned char)': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:32: multiple definition of AS3935::_SPITransfer2(unsigned char, unsigned char)'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:32: first defined here
AS3935\AS3935.cpp.o: In function AS3935::reset()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:77: multiple definition of AS3935::reset()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:77: first defined here
AS3935\AS3935.cpp.o: In function AS3935::_rawRegisterRead(unsigned char)': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:43: multiple definition of AS3935::_rawRegisterRead(unsigned char)'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:43: first defined here
AS3935\AS3935.cpp.o: In function AS3935::registerRead(unsigned char, unsigned char)': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:66: multiple definition of AS3935::registerRead(unsigned char, unsigned char)'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:66: first defined here
AS3935\AS3935.cpp.o: In function AS3935::getWatchdogThreshold()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:209: multiple definition of AS3935::getWatchdogThreshold()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:209: first defined here
AS3935\AS3935.cpp.o: In function AS3935::getSpikeRejection()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:198: multiple definition of AS3935::getSpikeRejection()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:198: first defined here
AS3935\AS3935.cpp.o: In function AS3935::getNoiseFloor()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:187: multiple definition of AS3935::getNoiseFloor()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:187: first defined here
AS3935\AS3935.cpp.o: In function AS3935::lightningDistanceKm()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:172: multiple definition of AS3935::lightningDistanceKm()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:172: first defined here
AS3935\AS3935.cpp.o: In function AS3935::getMinimumLightnings()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:161: multiple definition of AS3935::getMinimumLightnings()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:161: first defined here
AS3935\AS3935.cpp.o: In function AS3935::interruptSource()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:146: multiple definition of AS3935::interruptSource()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:146: first defined here
AS3935\AS3935.cpp.o: In function AS3935::registerWrite(unsigned char, unsigned char, unsigned char)': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:55: multiple definition of AS3935::registerWrite(unsigned char, unsigned char, unsigned char)'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:55: first defined here
AS3935\AS3935.cpp.o: In function AS3935::clearStats()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:218: multiple definition of AS3935::clearStats()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:218: first defined here
AS3935\AS3935.cpp.o: In function AS3935::setWatchdogThreshold(int)': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:212: multiple definition of AS3935::setWatchdogThreshold(int)'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:212: first defined here
AS3935\AS3935.cpp.o: In function AS3935::setSpikeRejection(int)': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:201: multiple definition of AS3935::setSpikeRejection(int)'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:201: first defined here
AS3935\AS3935.cpp.o: In function AS3935::setNoiseFloor(int)': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:190: multiple definition of AS3935::setNoiseFloor(int)'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:190: first defined here
AS3935\AS3935.cpp.o: In function AS3935::setOutdoors()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:182: multiple definition of AS3935::setOutdoors()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:182: first defined here
AS3935\AS3935.cpp.o: In function AS3935::setIndoors()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:177: multiple definition of AS3935::setIndoors()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:177: first defined here
AS3935\AS3935.cpp.o: In function AS3935::setMinimumLightnings(int)': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:164: multiple definition of AS3935::setMinimumLightnings(int)'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:164: first defined here
AS3935\AS3935.cpp.o: In function AS3935::enableDisturbers()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:156: multiple definition of AS3935::enableDisturbers()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:156: first defined here
AS3935\AS3935.cpp.o: In function AS3935::disableDisturbers()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:151: multiple definition of AS3935::disableDisturbers()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:151: first defined here
AS3935\AS3935.cpp.o: In function AS3935::powerDown()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:134: multiple definition of AS3935::powerDown()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:134: first defined here
AS3935\AS3935.cpp.o: In function AS3935::powerUp()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:137: multiple definition of AS3935::powerUp()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:137: first defined here
AS3935\AS3935.cpp.o: In function AS3935::calibrate()': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:81: multiple definition of AS3935::calibrate()'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:81: first defined here
AS3935\AS3935.cpp.o: In function AS3935': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:22: multiple definition of AS3935::AS3935(unsigned char ()(unsigned char), int, int)'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:22: first defined here
AS3935\AS3935.cpp.o: In function AS3935': C:\Users\office\Documents\Arduino\libraries\AS3935/AS3935.cpp:22: multiple definition of AS3935::AS3935(unsigned char (
)(unsigned char), int, int)'
AS3935.cpp.o:C:\Users\office\AppData\Local\Temp\build4348146508195175771.tmp/AS3935.cpp:22: first defined here

Just an update, I have tried using Arduino 1.0.1, 1.0.3, and 1.0.4 with the same error. I am running Windows 7, and have rebooted. I have also re-downloaded the Lightning sensor library, but it still wont compile. Anyone have any thoughts? I would love to get this code on my Megs256!

Solved. I downloaded the Library a 3rd time from Git, and it compiled just fine. Not sure what was going on, but something kept getting corrupted.