NodeMCU doesn't seem to set digital pin low - arduino

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.

Related

how can i count pulses using analog pin of arduino

The frequency of the pulses range from 1-10000 Hz and voltage ranges from 1-5 volt. I have tried the following code, its working for digital pins but not for analog.Do you guys have any solution for it.
int pin = A0;
volatile unsigned int pulse = 0;
void setup()
{
Serial.begin(9600);
pinMode(pin, INPUT_PULLUP);
attachInterrupt(0, count_pulse, RISING);
}
void loop()
{
pulse=0;
interrupts();
delay(100);
noInterrupts();
Serial.print("Pulses per second: ");
Serial.println(pulse);
}
void count_pulse()
{
pulse++;
}
Different Arduino boards (Mega, Uno, Nano etc) are different in terms of which pins work with interrupts. You need to read the documentation for your board, or much better, use #ifdef to adapt to any board:
#ifdef __AVR_ATmega32U4__ // Leonardo has different int mapping
#ifdef __SAM3X8E__ // Due processor has different timer setup
#ifdef __AVR_ATmega328P__
Check out the documentation on arduino.cc/reference.
In short if you are using the arduino uno you can only use the digital pin #2 and #3 for attachinterrupt() operation... https://youtu.be/srr0TTRPPKU

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);

Unable to toggle Arduino State from HIGH to LOW after delay

functionality:
Arduino make use of the following:
1. IR sensor
2. LED Light
3. MotorFan
4. Relay
hence, when user approaches the IR sensor, it will give a serialPrint of '1' since it has detected proximity, this will then toggle the state of LED and motorfan from LOW to HIGH. However, after 5s, the state of motorfan will toggle to LOW from HIGH, while the state of LED will still remain HIGH and will remain as HIGH as long as the serialPrint is '1'.
However, when user leaves the proximity of the IR sensor, the LED state will toggle to LOW from HIGH after 10s.
What I have done:
Code that I have done:
const int signalPin = 1; //wire pin to analog for IR Sensor
//Motor-Fan Relay
byte FanRelay = 4;
byte LightRelay = 6;
int IRSignal; //variable signal, will hold the analog value read by Arduino
long duration;
int distance;
unsigned long Timer;
unsigned long Interval = 10000; //teh repeat Interval
unsigned long MotorFanOff = 5000;
void setup()
{
//Execute only once at startup
//pinMode (FanPin , OUTPUT) ; // Set pinMode for FanPin as OUTPUT, display
pinMode (signalPin, INPUT); //infared sensor line will be an input to the Arduino
pinMode(FanRelay, OUTPUT);
pinMode(LightRelay, OUTPUT);
Serial.begin(9600); // Open serial port to communicate with the Ultrasaonic Sensor
}
void loop()
{
//execute multiple times in a loop
IRSignal = analogRead(signalPin); //arduino reads the value from the infared sensor
distance = 9462 / (IRSignal -16.92);
if(distance < 30 && distance > 0)
{
Timer = millis();
// Write a pin of HIGH
Serial.println("1");
//Set motor-fan to operate
digitalWrite (FanRelay, HIGH);
digitalWrite (LightRelay, HIGH);
//After a delay of 5s, MotorFan will toggle to LOW
//Toggle MotorFan to LOW after 5s
if ((millis()-Timer)>MotorFanOff){
digitalWrite (FanRelay, LOW);
}
}
else
{
Serial.println("0");
//Check if Timer is longer than 10s
if ((millis()-Timer)>Interval){
digitalWrite (LightRelay, LOW);
digitalWrite (FanRelay, LOW);
}
}
delay(1000);
}
Issue:
At this point, when tested, both the state of the LED and motorfan will toggle from LOW to HIGH when the serialPrint is '1' from the IR sensor. However, the main issue that i am facing is that the state of the MOTORFAN does not toggle to LOW from HIGH after 5seconds, but both state will only toggle to LOW when serialPrint is '0'.
Hence, what have I done wrong? pls help.thanks.
Be careful! The first two pins on the Arduino are used for serial communication and break if you use them for something else. Switch over to higher pin numbers and the problem should go away.

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

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.

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);
}
}

Resources