Dayaan M. answered 11d
Computer Science Graduate with Computer Engineering Coursework
The whole thing is really a state machine. You read a mode number from the Serial monitor once, remember it, and then on every pass through loop() you do whatever that mode calls for. Here it is, and then I will go through the parts that matter.
const int LED1 = 2; // temp < 30
const int LED2 = 3; // 30 <= temp <= 60
const int LED3 = 4; // temp > 60
const int BUZZER = 5;
const int TEMP_PIN = A0;
const int PHOTO_PIN = A1;
int mode = 0;
void setup() {
Serial.begin(9600);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(BUZZER, OUTPUT);
Serial.println("Enter 0, 1 or 2 to pick a mode");
}
void allOff() {
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
noTone(BUZZER);
}
void loop() {
if (Serial.available() > 0) {
char c = Serial.read();
if (c >= '0' && c <= '2') {
mode = c - '0';
allOff();
Serial.print("Mode ");
Serial.println(mode);
}
}
if (mode == 0) {
allOff();
}
else if (mode == 1) {
int raw = analogRead(TEMP_PIN);
float volts = raw * 5.0 / 1024.0;
float tempC = (volts - 0.5) * 100.0; // TMP36
if (tempC < 30) {
digitalWrite(LED1, HIGH);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
}
else if (tempC <= 60) {
digitalWrite(LED1, LOW);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, LOW);
}
else {
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, HIGH);
}
}
else if (mode == 2) {
int photo = analogRead(PHOTO_PIN);
photo = constrain(photo, 54, 974);
int freq = map(photo, 54, 974, 500, 1000);
tone(BUZZER, freq);
}
}
The mode variable lives outside loop() on purpose. loop() runs over and over, so anything declared inside it would reset to zero every single pass and the mode would never stick. We only touch Serial when something is actually waiting, which is what Serial.available() is checking, and we subtract the character '0' to turn the character into a number. That works because the digit characters sit next to each other in order.
In mode 1, notice the three cases are written as if, else if, else rather than three separate ifs. Because the else if only runs when the first test already failed, we already know the temperature is at least 30, so the second test only has to check the upper end. I ran every temperature from −20 to 100 in steps of a tenth and exactly one LED comes on each time, with 30 and 60 both landing in the middle band the way the problem describes.
In mode 2 your hint is the right call. map(photo, 54, 974, 500, 1000) stretches the photoresistor range onto the tone range, so 54 gives 500 Hz and 974 gives 1000 Hz. I would add constrain() in front of it though. A photoresistor can easily read outside 54 to 974 in a very dark or very bright room, and map does not clamp, it just keeps following the same straight line. Without constrain a reading of 0 asks for 470 Hz and a reading of 1023 asks for 1026 Hz, both outside the range you were told to use. With constrain those become 500 and 1000.
Two honest notes. Your modes are listed as 0, 1 and 2, but the hint says mode 3. From the connections and the description it is clearly the buzzer and photoresistor mode, so I wrote it as mode 2. And you did not say which temperature sensor you have. The line converting the analog reading to degrees is the TMP36 formula, which is the common one in these kits, so if yours is different just swap that one line for your sensor's formula and everything else stays exactly the same.