How to initialize APDS-9930 ambient light / proximity sensor using ARDUINO Mega2560 - arduino

I have bought a "APDS-9930" ambient light sensor, which communicates over I2C (TWI) protocol. I intend to read the the ambient light level from it, using ARDUINO Mega2560 development board. As I searched the net, I found a modified ARDUINO library, based on APDS-9960, which claims to work with APDS-9930 on ARDUINO UNO. However, when used with Mega2560, It gives me "Error initializing" error. Does anyone here know how to handle this error?
I have already used "Wire.h" library in many ways, to read "CH0 ADC data register" with address 0x14, which holds the ambient level value (according to datasheet). The code is as follows:
#define DUMP_REGS
#include <Wire.h>
#include <APDS9930.h>
// Global Variables
APDS9930 apds = APDS9930();
float ambient_light = 0; // can also be an unsigned long
uint16_t ch0 = 0;
uint16_t ch1 = 1;
void setup() {
//analogReference(EXTERNAL);
// Initialize Serial port
Serial.begin(9600);
Serial.println();
Serial.println(F("--------------------------------"));
Serial.println(F("APDS-9930 - Ambient light sensor"));
Serial.println(F("--------------------------------"));
// Initialize APDS-9930 (configure I2C and initial values)
//if ( apds.init() ) {
// Serial.println(F("APDS-9930 initialization complete"));
//} else {
// Serial.println(F("Something went wrong during APDS-9930 init!"));
// }
// Start running the APDS-9930 light sensor (no interrupts)
//if ( apds.enableLightSensor(false) ) {
// Serial.println(F("Light sensor is now running"));
// } else {
// Serial.println(F("Something went wrong during light sensor init!"));
// }
#ifdef DUMP_REGS
/* Register dump */
uint8_t reg;
uint8_t val;
for(reg = 0x00; reg <= 0x19; reg++) {
if( (reg != 0x10) && \
(reg != 0x11) )
{
apds.wireReadDataByte(reg, val);
Serial.print(reg, HEX);
Serial.print(": 0x");
Serial.println(val, HEX);
}
}
apds.wireReadDataByte(0x1E, val);
Serial.print(0x1E, HEX);
Serial.print(": 0x");
Serial.println(val, HEX);
#endif
// Wait for initialization and calibration to finish
delay(500);
}
void loop() {
// Read the light levels (ambient, red, green, blue)
if ( !apds.readAmbientLightLux(ambient_light) ||
!apds.readCh0Light(ch0) ||
!apds.readCh1Light(ch1) ) {
Serial.println(F("Error reading light values"));
} else {
Serial.print(F("Ambient: "));
Serial.print(ambient_light);
Serial.print(F(" Ch0: "));
Serial.print(ch0);
Serial.print(F(" Ch1: "));
Serial.println(ch1);
}
// Wait 1 second before next reading
delay(1000);
}

As discussed in the comments above, the issue is hardware related.
On the Arduino Mega 2560 board there are two resistances tying lines SDA and SCK (pins 20 and 21 on the connector) to +5V.
With those pull-up resistances, it's not possible to interface with sensors working at 3.3V directly.
The solution is to add a level shifter or remove the resistances on the board and install them externally connecting them to 5V or 3.3V as necessary depending on the sensor you want to interface to.

Related

warning: overflow in implicit constant conversion [-Woverflow] in Arduino Mega 2560 WI-Fi R3

i want to record a long data for like 2 to 3 hours using microcontroller Arduino Mega 2560 WI-FI R3 but I got this warning in my code
below is the picture of the warning i got.
enter image description here
the warning come up when I put the time out constant more than 30000 milliseconds
below is the code I used for the Arduino
#include "DHT.h"
// Pin Definitions
#define DHT_PIN_OUT A1
#define DHTTYPE DHT11
#define MQ3_PIN_OUT A2
#define MQ4_PIN_OUT A3
#define MQ7_PIN_OUT A4
// Global variables and defines
// object initialization
DHT dht(DHT_PIN_OUT, DHTTYPE);
// define vars for testing menu
const int timeout = 180000; //define timeout of 1 hour
char menuOption = 0;
long time0;
// Setup the essentials for your circuit to work. It runs first every time your circuit is powered with electricity.
void setup()
{
// Setup Serial which is useful for debugging
// Use the Serial Monitor to view printed messages
Serial.begin(9600);
while (!Serial) ; // wait for serial port to connect. Needed for native USB
Serial.println("start");
dht.begin();
menuOption = menu();
}
// Main logic of your circuit. It defines the interaction between the components you selected. After setup, it runs over and over again, in an eternal loop.
void loop(){
if(menuOption == '1') {
delay(500); //delay 0.5 second
// DHT11 Humidity and Temperature Sensor
// Reading humidity in %
float dhtHumidity = dht.readHumidity();
// Read temperature in Celsius, for Fahrenheit use .readTempF()
float dhtTempC = dht.readTemperature();
float Alcohol = analogRead(MQ3_PIN_OUT);
float Methane = analogRead(MQ4_PIN_OUT);
float CarbonMonoxide = analogRead(MQ7_PIN_OUT);
Serial.print(F("Humidity: ")); Serial.print(dhtHumidity); Serial.print(F("[%]\t"));
Serial.print(F("Temp: ")); Serial.print(dhtTempC); Serial.print(F("[C]\t"));
Serial.print(F("Alcohol: ")); Serial.print(Alcohol); Serial.print(F(" \t"));
Serial.print(F("Methane: ")); Serial.print(Methane); Serial.print(F(" \t"));
Serial.print(F("Carbon Monoxide: ")); Serial.println(CarbonMonoxide); Serial.println(F(" \t"));
}
if (millis() - time0 > timeout){
menuOption = menu();
}
}
// Menu function for selecting the components to be tested
// Follow serial monitor for instrcutions
char menu(){
Serial.println(F("\nSensor Array"));
Serial.println(F("Press (1) to start the sensor array"));
while (!Serial.available());
// Read data from serial monitor if received
while (Serial.available()){
char c = Serial.read();
if (isAlphaNumeric(c))
{
if(c == '1')
Serial.println(F("Now running the sensor array"));
else{
Serial.println(F("illegal input!"));
menuOption = menu();
return 0;
}
time0 = millis();
return c;
}
}
}
sorry for my bad programming and silly question, I'm new to this kind of thing. and I just found out that people usually get answers from StackOverflow, so I just wanted to try asking because I have tried to google the answer but I can't find it.

Using arduino Nano 32 IOTs BLE to create LED display boards

I am working on a project for which I need to get a panel of 7 buttons to light up led strips on a display about 5m away. So far I have made it so I can control 1 led strip with one button and this works well. I am now confused on how to get the other 6 to connect to the same arduino via BLE. The idea is to have one arduino with all the buttons connected, then 1 arduino for each led strip. You press button 1 on the button arduino and this sends a signal to the display 1 arduino, lighting the display.
Here is my code so far, what would I need to do to it to add multiple buttons in ?
Thanks !!
//this code is loaded onto the board that is connected to the led strip
//if the code doesnt work it seems to kick start it by opening the serial monitor and then it will connect, not sure why this is
#include <ArduinoBLE.h>
#include <Adafruit_DotStar.h>
#include <SPI.h>
#define NUMPIXELS 144 // Number of LEDs in strip
#define BUTTON_PIN 9 //pin the button is on
#define DATAPIN 4 //the pin the data is plugged into
#define CLOCKPIN 5 //the pin the clock wire is plugged into
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // adress of the ledstrip that is referenced in the other set of code
Adafruit_DotStar strip(NUMPIXELS, DATAPIN, CLOCKPIN, DOTSTAR_BRG);
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
const int ledPin = 2; // pin to use for the LED
void setup() {
// set LED pin to output mode
pinMode(ledPin, OUTPUT);
// begin initialization
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
// set advertised local name and service UUID:
BLE.setLocalName("LED");
BLE.setAdvertisedService(ledService);
// add the characteristic to the service
ledService.addCharacteristic(switchCharacteristic);
// add service
BLE.addService(ledService);
// set the initial value for the characeristic:
switchCharacteristic.writeValue(0);
// start advertising
BLE.advertise();
Serial.println("BLE LED Peripheral");
strip.begin();
strip.show(); //pixels to 'off'
}
uint32_t white= strip.Color(255, 255, 255); //colour you want the lights
uint32_t off= strip.Color(0, 0, 0); //colour 'off'
void loop() {
// listen for BLE peripherals to connect:
BLEDevice central = BLE.central();
// if a central is connected to peripheral:
if (central) {
Serial.print("Connected to central: ");
// print the central's MAC address:
Serial.println(central.address());
// while the central is still connected to peripheral:
while (central.connected()) {
// if the remote device wrote to the characteristic,
// use the value to control the LED:
if (switchCharacteristic.written()) {
if (switchCharacteristic.value()) { // any value other than 0
strip.fill(white, 0, 144); //fill(Color,first pixel,last pixel)
strip.setBrightness(5); //set the brightness of the leds here, would keep about 40, doesnt like anything above that
strip.show(); //update the leds
delay(7000); //time you want the LEDs
strip.fill(off, 0, 144); //turns off leds
strip.setBrightness(0);
strip.show();
} else { // a 0 value
strip.fill(off, 0, 144);
strip.setBrightness(0);
strip.show();
}
}
}
// when the central disconnects, print it out:
Serial.print(F("Disconnected from central: "));
Serial.println(central.address());
}
}
//this code gets loaded onto the button board
#include <ArduinoBLE.h>
// variables for button
const int buttonPin = 2;
int oldButtonState = LOW;
void setup() {
// configure the button pin as input
pinMode(buttonPin, INPUT);
// initialize the BLE hardware
BLE.begin();
Serial.println("BLE Central - LED control");
// start scanning for peripherals
BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214"); //Put the adress of what you want the button to control here
}
void loop() {
// check if a peripheral has been discovered
BLEDevice peripheral = BLE.available();
if (peripheral) {
// discovered a peripheral, print out address, local name, and advertised service
Serial.print("Found ");
Serial.print(peripheral.address());
Serial.print(" '");
Serial.print(peripheral.localName());
Serial.print("' ");
Serial.print(peripheral.advertisedServiceUuid());
Serial.println();
if (peripheral.localName() != "LED") {
return;
}
// stop scanning
BLE.stopScan();
controlLed(peripheral);
// peripheral disconnected, start scanning again
BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
}
}
void controlLed(BLEDevice peripheral) {
// connect to the peripheral
Serial.println("Connecting ...");
if (peripheral.connect()) {
Serial.println("Connected");
} else {
Serial.println("Failed to connect!");
return;
}
// discover peripheral attributes
Serial.println("Discovering attributes ...");
if (peripheral.discoverAttributes()) {
Serial.println("Attributes discovered");
} else {
Serial.println("Attribute discovery failed!");
peripheral.disconnect();
return;
}
// retrieve the LED characteristic
BLECharacteristic ledCharacteristic = peripheral.characteristic("19b10001-e8f2-537e-4f6c-d104768a1214");
if (!ledCharacteristic) {
Serial.println("Peripheral does not have LED characteristic!");
peripheral.disconnect();
return;
} else if (!ledCharacteristic.canWrite()) {
Serial.println("Peripheral does not have a writable LED characteristic!");
peripheral.disconnect();
return;
}
while (peripheral.connected()) {
// while the peripheral is connected
// read the button pin
int buttonState = digitalRead(buttonPin);
if (oldButtonState != buttonState) {
// button changed
oldButtonState = buttonState;
if (buttonState) {
Serial.println("button pressed");
// button is pressed, write 0x01 to turn the LED on
ledCharacteristic.writeValue((byte)0x01);
} else {
Serial.println("button released");
// button is released, write 0x00 to turn the LED off
ledCharacteristic.writeValue((byte)0x00);
}
}
}
Serial.println("Peripheral disconnected");
A typical way of doing this with BLE would be for the button to be the Peripheral and the LED strip to be the Central. The Central would connect to the Peripheral and subscribe to notifications on the "button" characteristic. Typically libraries/hardware aren't setup to have multiple Centrals connected at the same time to one Peripheral. This would seem to rule out doing it this way with your required hardware setup.
An alternative would be to have the buttons as the Central and the LED strips as the Peripheral. The Central would already know the details of the Peripheral device and initiate a connection and then do a write when a button is pressed. I would expect there to be a lot of lag between the button being pressed and something happening on the LED strip with this setup.
Another alternative is to do this with connection-less BLE, if security isn't a concern. The button board could act as a BLE beacon and you could encode information about which button has been pressed in the Service Data or the Manufacturer Data. The LED strips would be scanners reading the data from the beacon. I am not very familiar with BLE libraries on Arduino, there appears to be the command to set the Manufacturer Data but I couldn't find any command to read the data.

Waterproofed water-temperature DS18B20 only returns -127 for degree in Celsius

For a project in university, I have to measure various quality of the water, including the temperature. The temperature sensor is DS18B20, and I use an Arduino Mega board to run the whole show. Individual running with DS18B20 only fails to return any meaningful number. Instead of 25C (or something like that), it returns -127.
The code below is from Dallas Temperature (with small changes, like having delay and removing some comment lines)
// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 48
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
void setup(void)
{
// start serial port
Serial.begin(9600);
Serial.println("Dallas Temperature IC Control Library Demo");
// Start up the library
sensors.begin();
}
void loop(void)
{
delay(500);
sensors.requestTemperatures(); // Send the command to get temperatures
Serial.println("DONE");
Serial.print("Temperature for the device 1 (index 0) is: ");
Serial.println(sensors.getTempCByIndex(0));
delay(2500);
}
This one is actually from the Wiki page of DFRobot (where my sensor is originated from)
#include <OneWire.h>
int DS18S20_Pin = 48; //DS18S20 Signal pin on digital 48
//Temperature chip i/o
OneWire ds(DS18S20_Pin); // on digital pin 48
void setup(void) {
Serial.begin(9600);
}
void loop(void) {
float temperature = getTemp();
Serial.println(temperature);
delay(100); //just here to slow down the output so it is easier to read
}
float getTemp(){
//returns the temperature from one DS18S20 in DEG Celsius
byte data[12];
byte addr[8];
if ( !ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
return -1000;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return -1000;
}
if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Device is not recognized");
return -1000;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
byte present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for (int i = 0; i < 9; i++ ) { // we need 9 bytes
data[i] = ds.read();
}
ds.reset_search();
byte MSB = data[1];
byte LSB = data[0];
float tempRead = ((MSB << 8) | LSB); //using two's compliment
float TemperatureSum = tempRead / 16;
return TemperatureSum;
}
This specific code returns -1000 every time, which I presume is the equivalence of -127 above.
Edit: The problem was identified as faulty electric wire. Yes, hardware problem.
From the library:
// Error Codes
#define DEVICE_DISCONNECTED_C -127
https://github.com/milesburton/Arduino-Temperature-Control-Library/blob/b34be08d603242bb534e7b717dac48baf60c5113/DallasTemperature.h#L36
So you're device is not connected / not communicating. Check your wiring and your pin numbers.

Will a CAN Bus network with 2 Arduino / MCP2515 nodes work?

I'd like to set up a CAN network of multiple nodes using Arduino Pro Minis and MCP2515 cards. But I can't get the Receive to work.
#include <mcp_can.h>
#include <SPI.h>
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128];
#define CAN0_INT 2 // Set INT to pin 2
MCP_CAN CAN0(10); // Set CS to pin 10
void setup() {
Serial.begin(115200);
// Initialize MCP2515 running at 8MHz with a baudrate of 125kb/s
// and the masks and filters disabled.
while (CAN_OK != CAN0.begin(MCP_ANY, CAN_125KBPS, MCP_8MHZ)) {
Serial.println("CAN BUS Module Failed to Initialize.");
}
Serial.println("MCP2515 Initialized Successfully!");
CAN0.setMode(MCP_NORMAL);
pinMode(CAN0_INT, INPUT); // Configuring pin for /INT input
}
void loop() {
if(!digitalRead(CAN0_INT)) { // If CAN0_INT is low, read receive buffer
CAN0.readMsgBuf(&rxId, &len, rxBuf); // Read data: len = data length, buf = data byte(s)
if((rxId & 0x80000000) == 0x80000000) // Is ID standard (11 bits) or extended (29 bits)?
sprintf(msgString, "Extended ID: 0x%.8lX DLC: %1d Data:", (rxId & 0x1FFFFFFF), len);
else
sprintf(msgString, "Standard ID: 0x%.3lX DLC: %1d Data:", rxId, len);
Serial.print(msgString);
if((rxId & 0x40000000) == 0x40000000) { // Is message a remote request frame?
sprintf(msgString, " REMOTE REQUEST FRAME");
Serial.print(msgString);
} else {
for(byte i = 0; i<len; i++) {
sprintf(msgString, " 0x%.2X", rxBuf[i]);
Serial.print(msgString);
}
}
Serial.println();
}
}
However, all I get out are the error messages, including this:
Entering Configuration Mode Failure
What am I missing here?
I got the circuit to work. The 2-node CAN Bus is communicating.
I found this site and made a couple of changes:
My Arduino ProMini MISI, MISO pins were not aligned with the SI, SO pins on the MCP2515s.
I used the CAN_BUS_Shield library.

MicroSD reader causing RFID reader to fail

I have a sketch running a MFRC522 RFID reader which works fine but my aim is to log the card swipes on a microSD card.
The problem is that as soon as I add the SD card reader, whether it is initialised or not, the RFID reader stops working.
It seems to be a problem on the SPI bus. I have tried adding pull up resistors to the circuit and setting the chip select pins to HIGH before initialising either of the boards but nothing seems to work.
Here is my code:
#include <SPI.h>
#include <MFRC522.h>
#include <SD.h>
// RFID constants & objects
#define RFPin 10
#define resetPin 9
MFRC522 mfrc522(RFPin, resetPin);
// SD constants
#define SDPin 8
// Other global variables
String IDString;
byte IDList[4];
void setup() {
pinMode(2, OUTPUT);// For testing
// Set both chip select pins high
pinMode(SDPin, OUTPUT);
digitalWrite(SDPin, HIGH);
pinMode(RFPin, OUTPUT);
digitalWrite(RFPin, HIGH);
delay(10);
// Init serial bus
Serial.begin(9600);
// Wait for serial bus to open
while (!Serial);// Opens even when not USB connected
// Init SPI bus
SPI.begin();
// Initialise RFID board
mfrc522.PCD_Init();
delay(1000);// Just in case SPI is still busy
// Initialise SD card board
if (!SD.begin(SDPin)) {
// SD card board failed to initialise
Serial.println("SD failed");
return;
}
}
void loop() {
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
for(int i = 0; i < 4; i++) {
digitalWrite(2, HIGH);
delay(100);
digitalWrite(2, LOW);
delay(100);
}
IDString = "";
// Get 4 byte ID
for (int i = 0; i < 4; i++) {
IDList[i] = mfrc522.uid.uidByte[i];
// Serial.print(IDList[i], HEX);
if(IDList[i] < 16) {
IDString += "0" + String(IDList[i], HEX) + "-";
} else {
IDString += String(IDList[i], HEX) + "-";
}
}
mfrc522.PICC_HaltA(); // Stop reading
IDString = IDString.substring(0, IDString.length() - 1);
Serial.println(IDString);
.
.
.
Rest of code
Everything initialised ok but Once in the main loop, the program never gets past the first statement: to check if an RFID card is present.
Can anybody help?
Could it be de to the fact that the RFDI board is 3.3V driven and the SD board is 5V driven (but has a 3.3V regulator)? Each has it's own separate power wire
EDIT #1:
When the MicroSD board is plugged in but not powered the RFID board works fine
I have also tried adding a subroutine to pull both chip select pins high at the beginning of every loop to no avail.
EDIT #2:
The SD board works in this sketch and I can get the card details from it.
EDIT #3:
The RFID card works again once I remove the MISO line from the SD board.
Obviously the SD module isn't releasing the MISO line...
It's not the most elegant solution but I have it working now by attaching an NPN transistor between the MISO output of the SD board and the MISO line to pin 12. It takes one further pin to block/unblock the MISO line to be used by the SD board but it works.
As I said this is not elegant and I would still be eager to hear a better solution.

Resources