Using a "big sound" module with arduino to create a decibel meter - arduino

I am trying to create a sound meter to measure the decibels in a room and I am currently using a nodemcu 12e as I want to insert those measures to a row in a mySQL server and a "big sound module" (https://tkkrlab.nl/wiki/Arduino_KY-038_Microphone_sound_sensor_module).
The only thing I have achieved so far is to get the raw values of the sensor, as they don't seem to change, although I have tried to adjust the gain turning the screw in the microphone, with no result, as it seems to stay in the same values even when playing loud music.
It seems to react to loud noises, and clapping makes the output to spike up - allowing me to control that lighting up the connected led:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
const char* ssid = "yourssid";
const char* password = "yourpass";
ESP8266WebServer server(80);
const int led = 13;
int sensorPin = A0; // select the input pin for the potentiometer
int ledPin = D7; // select the pin for the LED
int sensorValue = 0; // variable to store the value coming from the sensor
void setup(void){
pinMode(led, OUTPUT);
digitalWrite(led, 0);
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (MDNS.begin("esp8266")) {
Serial.println("MDNS responder started");
}
});
//SETUP SOUND SENSOR
pinMode (ledPin, OUTPUT);
}
void loop(void){
sensorValue = analogRead (sensorPin);
Serial.println (sensorValue);//, DEC);
if (sensorValue > 100){
digitalWrite (ledPin, HIGH);
delay (1000);
digitalWrite (ledPin, LOW);
}
}
I am reading the analog value of the sensor and I tried to get the lower values possible as seen I was trying to calibrate the mic. The values I am constantly getting are between 19 and 20:
As you can see, on clapping I get a spike of the value.
The thing is that the values don't change at all when loud music is playing, only getting different values when it detects a loud noise (like clapping). How can I change the code or system to get the values in decibels?

You might not get this running with this microphone module.
The mdule act as a switch. The switching threshold is set by the potentiometer on board of the microphone module.
What you would need is a low-level amlified microphone. Then you would get an input range from 0 (no noise) to 1023 (loud noise). This value then could be mapped to decibel. But again - not with this module.
Regards
Harry

To read a stream of audio signal via analog0 input you need a board that has an analog output. The board you're using has a Digital output which outputs a signal whenever it's threshold it's exceed the limit you set on the potentiometer (yes the potentiometer you were moving just set the limit when the microphone will output a digital pulse).
So you have you should purchase another microphone like this one.
The one you have only tells you if there is sound or no sound.

Related

NodeMCU doesn't seem to set digital pin low

I'm writing a simple project, using NodeMCU as my board. I have 2 analog devices: moisture sensor and brightness sensor. Since NodeMCU has only one analog pin, I try to power them in turns. To do so, I connect them to digital pins of NodeMCU. Digital pins output 3.3V 20-40mA in HIGH state (checked that with multimeter). That must be enough to power those devices. In the LOW state, according to Arduino IDE docs, voltage must be 0V (and that also was checked) and the sensor must not receive any current and, thus, must not output anything to A0. However, at the end I get correlated results: if I flash light at the photoresistor, humidity data is also affected. And vice-versa. How can I avoid it?
Here's the code, I'm using to do, what I described:
const int analogInputPin = A0; // Analog 0 (A0) on the board
// Several devices will use the same analog pin to send data
const int lightSensorResultPin = analogInputPin;
const int moistureSensorResultPin = analogInputPin;
const int lightSensorPowerPin = 16;
int lightSensorResult = 0;
const int moistureSensorPowerPin = 5;
int moistureSensorResult = 0;
void setup() {
Serial.begin(9600);
pinMode(lightSensorResultPin, INPUT);
pinMode(lightSensorPowerPin, OUTPUT);
digitalWrite(lightSensorPowerPin, LOW);
pinMode(moistureSensorResultPin, INPUT);
pinMode(moistureSensorPowerPin, OUTPUT);
digitalWrite(moistureSensorPowerPin, LOW);
}
void loop() {
/*==LIGHT SENSOR DATA READ BLOCK==*/
digitalWrite(lightSensorPowerPin, HIGH);
delay(1000);
lightSensorResult = analogRead(lightSensorResultPin);
digitalWrite(lightSensorPowerPin, LOW);
delay(1000);
/*==END OF LIGHT SENSOR DATA READ BLOCK==*/
/*==MOISTURE SENSOR DATA READ BLOCK==*/
digitalWrite(moistureSensorPowerPin, HIGH);
delay(1000);
moistureSensorResult = analogRead(moistureSensorResultPin);
digitalWrite(moistureSensorPowerPin, LOW);
delay(1000);
/*==END OF MOISTURE SENSOR DATA READ BLOCK==*/
Serial.print("Value on the light sensor: ");
Serial.println(lightSensorResult); // Light value. Low for bright
Serial.print("Value on the moisture sensor: ");
Serial.println(moistureSensorResult); // Moisture value. Low for wet
}
UPD: Here's the schematic
Instead of using digital outputs to switch on and off the different sensors, but combining their analog outputs, I would use an analog switch like 4066 to select which sensor you want to measure.

Why 2nd PIR sensor is always HIGH?

I an getting a constant HIGH from 'inputPintwo' on the serial monitor. When 'inputPin' goes HIGH the relay is triggered and works properly because 'inputPintwo' is also HIGH (all the time).
I have a Very similar setup to: 2 PIR motion sensors +Arduino
I am not using pin 0 or 1 like the above answered question. I have replaced the sensor with a different one, in case it was bad hardware. I also unplugged the sensor and it still reads HIGH. The jumper is on retriggering on both sensors.
int ledPin = 13;
int inputPin = 2;
int inputPintwo = 4;
int pirState = LOW;
int val = 0;
int valtwo = 0;
#define RELAY1 7
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(inputPin, INPUT);
pinMode(inputPintwo, INPUT);
pinMode(RELAY1, OUTPUT);
Serial.begin(9600);
}
void loop(){
val = digitalRead(inputPin);
valtwo = digitalRead(inputPintwo);
if (val == HIGH && valtwo == HIGH) {
digitalWrite(ledPin, HIGH);
if (pirState == LOW) {
Serial.println("Motion detected!");
pirState = HIGH;
Serial.println("Light ON");
digitalWrite(RELAY1,1);
delay(500);
digitalWrite(RELAY1,0);
delay(500);
digitalWrite(RELAY1,1);
delay(500);
digitalWrite(RELAY1,0);
delay(500);
digitalWrite(RELAY1,1);
}
}
else {
digitalWrite(ledPin, LOW);
if (pirState == HIGH){
Serial.println("Motion ended!");
digitalWrite(RELAY1,0);
pirState = LOW;
Serial.println("Light OFF");
}
}
}
I expect both sensors to go HIGH only when motion is detected, which will cause the relay to go on and off several times, then stay on until the timer runs out on the sensors.
To identify the problem I recommend you to start with checking the hardware. You will need voltmeter/multimeter.
Double check if you are interfacing the sensor properly (check datasheet). Didn't you forget to connect e.g. the pull-down resistors?
Check power supply voltage on sensors – is the voltage within
manufacturer specifications?
Check breadboard connections if you are using one.
Check sensor output behaviour (voltage), if there is or is not a movement. Is the voltage constant or not? Constant voltage means that PIR sensor is NOT working properly. Before performing of this test disconnect output from Arduino input.
If everything seems OK or you do not have voltmeter, try to disconnect the PIR sensor and connect a wire between Arduino pin 4 and ground. Does digitalRead(inputPintwo) return LOW? If yes, you know that reading of the pin state works fine.
Below please see some recommendations related to your code:
use #define directive or static const int variable type to define Arduino pins as you do it with relay output pin RELAY1.
Example:
#define LED_PIN 13
#define INPUT_PIN 2
#define INPUT_PINTWO 4
or
static const int ledPin = 13;
static const int inputPin = 2;
static const int inputPintwo = 4;
In your case, where you are only interested in digital value (LOW/HIGH), use built pull-up resistor on the input pins. Thus the log. voltage level on the floating input pin is defined (HIGH). If you do not use pull-up resistors, voltage can be either log. 0 (LOW) or log. 1 (HIGH), what can lead to strange program/state machine behaviour
To activate pull-up resistors in the input pins, use
pinMode(inputPin, INPUT_PULLUP);
pinMode(inputPintwo, INPUT_PULLUP);

NRF24L01 with ATTiny and Uno not connecting

I have an ATTiny85 connected to an NRF24L01+ module using this wiring diagram: diagram. The ATTiny85 periodically goes in and out of sleep to send some value to a receiver, an Arduino Uno. If the ATTiny is running off the Arduino power supply (3.3v), everything works correctly. When I run the ATTiny off of a separate CR2032 coin cell that delivers around 3v, the Arduino never receives any data. I have a status LED hooked up to the ATTiny to ensure that the ATTiny is waking correctly, which it is. Here's the code for both:
EDIT:
Connecting it to an external 3.3v not from the Uno makes everything work - why wouldn't the coin cell's voltage work? I think everything is rated below 2.8v, the CR2032 minimum.
ATTiny Code
#include <avr/sleep.h>
#include <avr/interrupt.h>
// Routines to set and claer bits (used in the sleep code)
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
#define CE_PIN 3
#define CSN_PIN 3 //Since we are using 3 pin configuration we will use same pin for both CE and CSN
#include "RF24.h"
RF24 radio(CE_PIN, CSN_PIN);
byte address[11] = "SimpleNode";
unsigned long payload = 0;
void setup() {
radio.begin(); // Start up the radio
radio.setAutoAck(1); // Ensure autoACK is enabled
radio.setRetries(15,15); // Max delay between retries & number of retries
radio.openWritingPipe(address); // Write to device address 'SimpleNode'
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);
delay(500);
digitalWrite(4, LOW);
delay(500);
digitalWrite(4, HIGH);
delay(500);
digitalWrite(4, LOW);
delay(500);
digitalWrite(4, HIGH);
delay(500);
digitalWrite(4, LOW);
delay(1000);
setup_watchdog(6);
}
volatile int watchdog_counter = 0;
ISR(WDT_vect) {
watchdog_counter++;
}
void loop()
{
sleep_mode(); //Go to sleep!
if(watchdog_counter >= 5)
{
digitalWrite(4, HIGH);
watchdog_counter = 0;
payload = 123456;
radio.write( &payload, sizeof(unsigned long) ); //Send data to 'Receiver' ever second
delay(1000);
digitalWrite(4, LOW);
}
}
//Sleep ATTiny85
void system_sleep() {
cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable();
sleep_mode(); // System actually sleeps here
sleep_disable(); // System continues execution here when watchdog timed out
sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON
}
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {
byte bb;
int ww;
if (ii > 9 ) ii=9;
bb=ii & 7;
if (ii > 7) bb|= (1<<5);
bb|= (1<<WDCE);
ww=bb;
MCUSR &= ~(1<<WDRF);
// start timed sequence
WDTCR |= (1<<WDCE) | (1<<WDE);
// set new watchdog timeout value
WDTCR = bb;
WDTCR |= _BV(WDIE);
}
Receiver Code
#define CE_PIN 7
#define CSN_PIN 8
#include <SPI.h>
#include "RF24.h"
RF24 radio(CE_PIN, CSN_PIN);
byte address[11] = "SimpleNode";
unsigned long payload = 0;
void setup() {
while (!Serial);
Serial.begin(115200);
radio.begin(); // Start up the radio
radio.setAutoAck(1); // Ensure autoACK is enabled
radio.setRetries(15,15); // Max delay between retries & number of retries
radio.openReadingPipe(1, address); // Write to device address 'SimpleNode'
radio.startListening();
Serial.println("Did Setup");
}
void loop(void){
if (radio.available()) {
radio.read( &payload, sizeof(unsigned long) );
if(payload != 0){
Serial.print("Got Payload ");
Serial.println(payload);
}
}
}
Is the problem here that the ATTiny and Uno need to be turned on at the same time to establish a connection, or is it something to do with the battery, or something else entirely? Any help would be appreciated.
I'm experiencing the same problem when running Arduino Nano from a battery.
Nano has a 3.3V pin that I'm using for powering the NRF24L01+ module.
When the voltage from my battery-pack drops under 3.3V, the 3.3V pin voltage also drops. After few minutes, the RF module is not sending any messages.
I fixed the problem temporarily by routing the battery through a 12V step-up regulator that I bought earlier for a different project. These 12V then go to the "UN" pin on Nano which accepts 6-20V. This setup works nicely but is definitely not optimal.
Therefore I'm planning to use a 3.3V step-up regulator such as Pololu 3.3V Step-Up Voltage Regulator U1V11F3 which, according to the supplier, can efficiently generate 3.3V from input voltages as low as 0.5V.
I think this might be helpful to your project as well.

BLUNO Distance Monitoring Project

I'm trying to do a project where BLUNO (Arduino UNO + BLE) will connect to an iBeacon and make use of the RSSI detected.
I've already made contact between the BLUNO and the iBeacon through the AT commands. I can get RSSI result in the Arduino IDE serial monitor when I ping it with AT commands.
My problem now is in sending those AT commands through an Arduino sketch. I know I've to use Serial Communication, but my Serial.Available function never returns more than 0.
void setup() {
pinMode(13, OUTPUT);
Serial.begin(115200);
Serial.print("+++\r\n");
Serial.print("AT+RSSI=?\r\n");
}
void loop(){
if(Serial.available()){
digitalWrite(13, HIGH);
delay(5000);
}
}
What is irritating me is that I can connect BLUNO to my iPhone and get the RSSI on the serial monitor through AT commands. But that above code doesn't work!
Any help?
I'm almost done with the whole project for now.
my mistake in the last code was the initiation part that has to be done before the AT commands. The right way is
Serial.begin(115200); //Initiate the Serial comm
Serial.print("+");
Serial.print("+");
Serial.print("+"); // Enter the AT mode
delay(500); // Slow down and wait for connection establishment
instead of
Serial.print("+++\r\n");
so yeah the rest is kind of alright. Keep in mind that this BLE thing REALLY sucks in terms of accuracy in locating a beacon. The RSSI reading keep fluctuating and the calculated distance using the simplified equation here somewhere on Stack overflow is REALLY unreliable.
So yeah keep that in mind yo!
Here's my full code just for reference.
// while the AT connection is active, the serial port between the pc and the arduino is occuipied.
// You can manipluate the data on arduino, but to display on the serial monitor you need to exit the AT mode
char Data[100];
char RAW[3];
int INDEX;
char Value = '-';
void setup() {
pinMode(13, OUTPUT); // This the onboard LED
pinMode(8, OUTPUT); // This is connected to the buzzer
Serial.begin(115200); //Initiate the Serial comm
Serial.print("+");
Serial.print("+");
Serial.print("+"); // Enter the AT mode
delay(500); // Slow down and wait for connectin establishment
}
void loop(){
Serial.println("AT+RSSI=?"); // Ask about the RSSI
for(int x=0 ; Serial.available() > 0 ; x++ ){ // get the Enter AT mode words
//delay(20); // Slow down for accuracy
Data[x] = Serial.read(); // Read and store Data Byte by Byte
if (Data[x] == Value ) // Look for the elemnt of the array that have "-" that's the start of the RSSI value
{
INDEX=x;
}
}
//Serial.println("AT+EXIT");
RAW[0] = Data[INDEX]; // Copy the RSSI value to RAW Char array
RAW[1] = Data[INDEX+1];
RAW[2] = Data[INDEX+2];
RAW[3] = Data[INDEX+3];
int RSSI = atoi(RAW); //Convert the Array to an integer
//Serial.println(RSSI);
//delay(200); // Give the program time to process. Serial Comm sucks
double D = exp(((RSSI+60)/-10)); //Calculate the distance but this is VERY inaccurate
//Serial.println(D);
if (D>1.00) // If the device gets far, excute the following>>
{
digitalWrite(13, HIGH);
digitalWrite(8, HIGH);
delay(500);
digitalWrite(13, LOW);
digitalWrite(8, LOW);
delay(500);
}
}

Arduino Serial.read() from xbee if statement

I am trying to finish a small project with a moisture sensor connected to a Fio V3.
I have also attach a Xbee S1 module to Fio's socket.
I have upload the following code to Fio:
int igrasia = 7;
void setup()
{
Serial1.begin(9600);
pinMode(igrasia, INPUT_PULLUP);
}
void loop(){
int sensorVal = digitalRead(igrasia);
if (sensorVal == HIGH) {
Serial1.println("0"); // Send OK to xbee
}
else {
Serial1.println("1"); // Send NOT OK to xbee
}
delay(5000);
}
On my computer using the Xbee USB explorer I am receiving correct data on X-CTU every 5 seconds.
Zero (0) while the sensor is outside a glass of water and one (1) while the sensor is in the glass of water.
I want to read these bytes to an Arduino Uno with a LCD screen attached and an Xbee shield. For this reason I have uploaded to Uno the following code:
#include <SPI.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x38,16,2); // set the LCD address to 0x20 for a 16 chars
void setup(){
Serial.begin(9600);
//configure pin2 as an input and enable the internal pull-up resistor
// pinMode(8, INPUT_PULLUP);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
lcd.init(); // initialize the lcd
}
void loop(){
if(Serial.available())
{
char getData = Serial.read();
if (getData == '1')
{
Serial.print(getData);
digitalWrite(13, HIGH);
lcd.clear();
lcd.setCursor (0,0); // go to start of 1st line
lcd.print("ATTENTION !!!!");
lcd.setCursor (0,1); // go to start of 1st line
lcd.print("WET environment");
}
else {
Serial.print(getData);
digitalWrite(13, LOW);
lcd.clear();
lcd.setCursor (0,0); // go to start of 1st line
lcd.print("dry environment");
lcd.setCursor (0,1); // go to start of 1st line
lcd.print("all looks good!");
}
}
}
It doesn't work properly :- (
I have correct functionality for 0 and while the sensor is outside the water. LCD monitor shows "dry environment".
But as soon as I place the sensor in the water, LCD is not working as required.
Even if I leave the sensor in the water the LCD still displays "dry environment".
I tried the sensor connected directly to Uno with the LCD attached and it works!
I suppose something is wrong with the serial.read() and/or my If / loop statement on UNO.
Any suggestions or advice?
When you transmit the data, you're sending it as a String "1", "0".
On the receiver, you're testing for characters '1', '0'. Strings are terminated with a null character (/u0000), whereas characters are not. Therefore the condition is always failed. You could try transmitting and testing characters only.

Resources