I am an inexperienced coder but am trying to learn. I'm sure my code is awkward but I would really appreciate any help. I hope I am asking the question properly.
I am working on a fun Arduino project for cosplay which has an LCD screen, a mp3 player and an old battery test meter attached. The mp3 player works fine. Currently the text on the LCD display and the needle on the meter are controlled by the analog input from a photo transistor. The code below is working ok but the issue I am having is that when there are different lighting conditions in the room, the values from the photo transistor are no longer 1024 and 0.
I am trying to map the actual values to say "2.8" (I need to include one decimal place) on the LCD screen as the top end and 0.0 as the low value (that's what I need for the prop to say on the screen). What I really need is for the code to do is take the analog values from the photo resistor (edited, should say photo transistor) that are greater or equal to 500 as the top number and less than 20 as the lower so it will work in varying light conditions when I surreptitiously interact with the photo resistor.
#include <LiquidCrystal.h> // include the library codes
#include <SoftwareSerial.h>
#include <Arduino.h>
#include <JQ6500_Serial.h>
#define phototransistorPin A1
#define meterPin 5
SoftwareSerial mySerial(3, 2); // talk to mp3 player
JQ6500_Serial mp3(mySerial);
LiquidCrystal lcd(13, 12, 11, 10, 9, 8); // initialize the library with the numbers of the interface pins
void setup()
{
delay(2000); // allow time to cover the trigger with finger.
mySerial.begin(9600);
mp3.reset();
mp3.setVolume(20); // sets mp3 player's volume
mp3.setLoopMode(MP3_LOOP_ALL); // plays the sound effect on loop
mp3.play();
lcd.begin(16, 2); // set up the LCD's number of columns and rows
}
void loop()
{
float Percentage = (analogRead(phototransistorPin) / 1024.0) * 2.9;
float PercentageRound = Percentage;
int meterPower = (analogRead(phototransistorPin) / 1024.0) * 255; //the power range of the meter
lcd.setCursor(5, 0); // set the cursor to column 5, line 0
lcd.print(PercentageRound, 1); //print value to 1 decimal place on LCD Display
lcd.setCursor(9, 0); // set the cursor to column 9, line 0
lcd.print("MJ");
analogWrite(meterPin, meterPower);
}
You are talking about photo transistor and at other places you write photo-resistor
photo-transistor / photo-resistor are completely different devices.
Simply connecting them to an analog-IO-pin does not work good. The minimum would be to have a voltage-divider. The value of the second resistor highly depends on the type of photo-transistor / photo-resistor.
Some photo-resistors have a pretty limited range of light where they change resistance.
So the minimum is that you provide a datasheet of exact that component that you are using.
If you can't provide a datasheet post a picture where the device can be seen in detail
to at least decide photo-transistor or photo-resistor.
If no datasheet is available in both cases analog measurings must be done to analyse the characteristics of the component.
The microcontroller-world is not super-standardised like USB-devices. You have to take care of more details than just "does the plug fit into the socket".
You should provide a pure functional description.
pure-functional means no code no numbers just normal words that explain the principle
with words like "environment with low light-level" "environment with high light-level"
etc.
a photo transistor is more than likely to be for a specific wavelength (e.g. infrared, IR) paired with an LED that emits that wavelength.
the output of a phototransistor will be exponentially proportional to the intensity of the light it receives, but incandescent lights and sunlight contain a lot of IR
the resistance of a photo resistor changes more proportional to the light. it would typically be put in series with another fixed resistor and analogRead() can be used to measure the change in resistance
Thank you for taking the time to reply. It is a phototransistor. It came in a kit with a book about learning Arduino so it I didn't receive a datasheet with it. Below is how I have it hooked up to my Pro Mini (5V).
Usually NPN-transistors have the Emitter connected to ground.
So a typical NPN-circuit looks like this
position of phototransistor and resistor changed.
This means the resistor would work as a pull-up-resistor.
As long as the foto-transistor receives no light the transistor is non-conductand.
In this case the analog input senses Vcc. The resistor "pull-up" the analog pin to Vcc
If the foto-transistor receives light the transistor becomes conductant.
The voltage "drops" across the resistor and the analog input will sense (almost) groundNot exactly 0,00 V maybe 0,1V.
Hi, I appreciate the help very much, I will try to explain properly. The code shown below and my circuit work the way I initially wanted. When a bright light hits the photo transistor, the LCD displays "2.8" which is the number I need for the prop. When there is no light, it displays "0.0". The problem is that the ambient lighting in the room varies. So I would like to use upper and lower limits that are anything greater than or equal to about 500 to (instead of 1023) prints "2.8" and anything less than or equal to 30 prints "0.0". I need the one decimal place.
The mp3 part of the code works fine, please ignore.
#include <LiquidCrystal.h> // include the library codes
#include <SoftwareSerial.h>
#include <Arduino.h>
#include <JQ6500_Serial.h>
#define phototransistorPin A1
#define meterPin 5
SoftwareSerial mySerial(3, 2); // talk to mp3 player
JQ6500_Serial mp3(mySerial);
LiquidCrystal lcd(13, 12, 11, 10, 9, 8); // initialize the library with the numbers of the interface pins
void setup()
{
delay(2000); // allow time to cover the trigger with finger.
mySerial.begin(9600);
mp3.reset();
mp3.setVolume(20); // sets mp3 player's volume
mp3.setLoopMode(MP3_LOOP_ALL); // plays the sound effect on loop
mp3.play();
lcd.begin(16, 2); // set up the LCD's number of columns and rows
}
void loop()
{
float Percentage = (analogRead(phototransistorPin) / 1024.0) * 2.8;
float PercentageRound = Percentage;
int meterPower = (analogRead(phototransistorPin) / 1024.0) * 255; //the power range of the meter
lcd.setCursor(5, 0); // set the cursor to column 5, line 0
lcd.print(PercentageRound, 1); //print value to 1 decimal place on LCD Display
lcd.setCursor(9, 0); // set the cursor to column 9, line 0
lcd.print("MJ");
analogWrite(meterPin, meterPower);
}
void loop()
{
int reading = analogRead(phototransistorPin);
int display = map(constrain(reading, 30, 500), 30, 500, 0, 280);
int meterPower = reading / 4; //the power range of the meter
lcd.setCursor(5, 0); // set the cursor to column 5, line 0
lcd.print(display/10);
lcd.print(".");
lcd.print(display%10); //print value to 1 decimal place on LCD Display
lcd.setCursor(9, 0); // set the cursor to column 9, line 0
lcd.print("MJ");
analogWrite(meterPin, meterPower);
}
void loop()
{
static int lastDisplay = -1;
int reading = analogRead(phototransistorPin);
int display = map(constrain(reading, 30, 500), 30, 500, 0, 280);
int meterPower = reading / 4; //the power range of the meter
if (display != lastDisplay) {
lastDisplay = display;
char buffer[21];
sprintf(buffer, "%2d.%1dMJ", display/10, display%10);
lcd.setCursor(5, 0); // set the cursor to column 5, line 0
lcd.print(buffer);
}
analogWrite(meterPin, meterPower);
}
I loaded it up and got the following results. It registered 28.0 (not 2.8) on the LCD display when exposed to light. When covered, it displayed numbers close to zero in rapid succession without stopping. Unfortunately, about 15 seconds into the test, the whole thing stopped working, even the mp3 sound stopped. Fortunately, I when I reloaded my previous code and it works again.
I finally solved the problem, I am posting the code in case it helps anyone else with a similar issue.
Thank you to all who took time to help.
#include <LiquidCrystal.h> // include the library codes
#include <SoftwareSerial.h>
#include <Arduino.h>
#include <JQ6500_Serial.h>
#define phototransistorPin A1
#define meterPin 5
SoftwareSerial mySerial(3, 2); // talk to mp3 player
JQ6500_Serial mp3(mySerial);
LiquidCrystal lcd(13, 12, 11, 10, 9, 8); // initialize the library with the numbers of the interface pins
void setup()
{
delay(2000); // allow time to cover the trigger with finger.
mySerial.begin(9600);
mp3.reset();
mp3.setVolume(20); // sets mp3 player's volume
mp3.setLoopMode(MP3_LOOP_ALL); // plays the sound effect on loop
mp3.play();
lcd.begin(16, 2); // set up the LCD's number of columns and rows
}
void loop()
{
float pinVal = analogRead(phototransistorPin);
float Percentage = (pinVal / 1024.0) * 2.8;
if (pinVal < 30) Percentage = 0;
if (pinVal > 500) Percentage = 2.8;
int meterPower = (analogRead(phototransistorPin) / 1024.0) * 255; //the power range of the meter
lcd.setCursor(5, 0); // set the cursor to column 5, line 0
lcd.print(Percentage, 1); //print value to 1 decimal place on LCD Display
lcd.setCursor(9, 0); // set the cursor to column 9, line 0
lcd.print("MJ");
analogWrite(meterPin, meterPower);
}
My bad, the 280 figure in my suggested code should have been 28.
How is that different from what you wanted it to do, or what your code above does?
There is nothing in my suggested code that would cause that to happen. Was the crash consistent, repeatable? Otherwise the crash sounds like an unrelated coincidence.