Hey all I am new to Arduino and MCU's in general. My initial attempt at posting was lost after about an hour of typing
Also, apologies if this is in the wrong thread.
So this is going to be somewhat more concise and save you from a bit of the background I had before.
Just note the only formal programming learning I have had was over a decade ago as an elective in college, was C++, but don't remember any of it. Have dabbled in Python and BATCH over the years but just surface stuff.
Objectives
-ATtiny85 MCU device to power on and off TV based on proximity sensor readings.
-Continuously monitor for person/object (3 year old son too close to TV)
-If within X range for Y seconds power off TV (90cm for 6 seconds).
-Monitor now with intent to power on TV
-If nothing within X range for Y seconds power on TV.
-Repeat
Parts So far...
-Arduino Uno R3
-Sharp GP2Y0A60SZLF Analog Distance Sensor 10-150cm
-ATtiny85V-10PU
-OP293A IR Emitter
-Random Blue LED
-2x 220 ohm resistor
-1x 100uf cap
Unfortunately and kind of fortunately I was unable to find a DIY or Instructable on this type of thing so I've done more piecing from similar projects and other stuff on my own and have probably learned more than just following a step-by-step.
Schematic This is my first attempt at drawing one (don't be too judgmental
)
Code (For ATtiny85)
#include <IRremote.h>
unsigned int power[] = {4550, 4400, 600, 1650, 550, 1650, 600, 1650,
550, 550, 600, 500, 600, 550, 550, 550, 600, 500, 600, 1650, 600, 1600, 600,
1650, 550, 550, 600, 500, 600, 550, 600, 500, 600, 500, 650, 450, 650, 1600,
600, 500, 650, 450, 650, 500, 600, 500, 600, 500, 600, 550, 600, 1600, 600,
500, 650, 1600, 650, 1550, 650, 1600, 650, 1550, 650, 1600, 650, 1600, 600
};
IRsend irsend;
const int statusled = 0; //Status led (ON when device turns TV OFF)
const int sensorpin = A1; //PB7 -Sharp Sensor Input -
int state = 1;
const long interval = 6000; //6 seconds for monitoring proximity(s)
void setup() {
pinMode(statusled, OUTPUT);
}
void loop() {
int sensorValue = (analogRead(sensorpin));
double distance = 187754 * pow(sensorValue, -1.51); //distance value form proximity sensor (calculated to centimeters)
unsigned long currentMillis = millis(); //value current time
while (state == 1) { //while loop to power TV OFF
sensorValue = analogRead(sensorpin); //
distance = 187754 * pow(sensorValue, -1.51); //getting new distance value
unsigned long timer1 = millis(); //value for timer1
if (timer1 - currentMillis >= interval) state = PowerTog(state, 1); //if timer reaches 6 secs call PowerTog - pass state and proximity breach
if (state == 0) break; //if TV state OFF leave while loop
if (distance > 90) break; //if poximity above minimum leave loop
}
currentMillis = millis();
while (state == 0) { //while loop to power TV back ON
sensorValue = analogRead(sensorpin); //
distance = 187754 * pow(sensorValue, -1.51); //getting new distance value
unsigned long timer2 = millis(); //value for timer2
if (timer2 - currentMillis >= interval) state = PowerTog(state, 0); //if timer reaches 6 secs call PowerTog - pass state and proximity clear
if (state == 1) break; //if TV state ON leave while loop
if (distance <= 90) break; //if poximity below minimum leave loop
}
}
int PowerTog(int state, int prox) {
if (prox == 1 && state == 1) { //proximity below minimum and TV state is ON
irsend.sendRaw(power, 68, 38); // Power off TV
digitalWrite(statusled, HIGH); //Sensor has powered off TV and is monitoring to power TV back ON.
return 0; //TV state now OFF
}
if (prox == 0 && state == 0) { //proximity is above minimum and TV state is OFF
irsend.sendRaw(power, 68, 38); //
irsend.sendRaw(power, 68, 38); // Power on TV (Dont know why but requires 3 signals)
irsend.sendRaw(power, 68, 38); //
digitalWrite(statusled, LOW); //Sensor back to initial state
return 1; //TV state now ON
}
else return state; //anything else return state
}
I am 100% sure there are better and more efficient ways to do the above, unfortunately I do not know those ways. It was hard not to use GOTO as it was, damn Batch(
, I'm such a begginer goto doesn't bug me, but read how it should only be used as a last resort etc etc).
If you would like to share, I am open to better ways but please provide good examples and/or ways to implement that doesn't break anything, or if so, how to fix it.
Library & Cores
https://github.com/z3t0/Arduino-IRremote
https://github.com/SpenceKonde/ATTinyCore
https://code.google.com/archive/p/arduino-tiny/ (Had to make new file boards.txt and copy and paste from Prospective Boards.txt)
A little background
I am using the Adruino as ISP ( initially IDE 1.6.8 ) method to burn bootloader and upload the sketch - had some setbacks at first but have this method down now.
Initially the ATtiny85 uploaded with basic sketches had no effect on the TV - don't know if it was the Core I was using (different from the ones posted) or the timing differences and delays. So I found some guides on tuning with TinyTuner using the Arduino as a USB to Serial adapter or an FTDI adapter - bought an FTDI (Prime is awesome - so fast). But neither worked - Could never get data on the Serial Monitor.
At the time my Core only had 8mhz internal or 16mhz external (did not know there was a 16mhz internal) - so thought I would have to do an external method - didn't know how to do this - googled a bit and found a crystal and calculated a pair of caps to go with it. As I waited on the crystals and caps ( not prime this time
) did some more googling and found additional cores (the ones listed above) that gave me the 16mhz internal option, both would burn but only one would accept the sketch upload. I don't know if it was the core change or coding changes I had made since, but now it was semi working. (I think I had figured out ways to remove the delays in the code and switched to the Raw Data form of power code irsend -maybe some more stuff).
But my TV wouldn't power back on, the device would initiate and change states - my TV would a clicking noise as if it sensed something. Don't know why this worked or how I randomly chose to try this but sending the power code 3x when the TV is off made it possible to power it back on. Also, during this time for some reason, I downloaded IDE 1.6.5. Now both cores allow burning the bootloader and upload of the sketch.
And Finally...
The Problem
My device works as intended, almost... I just happened to notice this bug and don't know how to go about debugging it
The device as it works now:
-Monitors and turns TV off when someone is within 90cm for 6 seconds
-LED lights up
-Monitors if someone is still within 90cm - changes nothing
- if nothing is detected for 6 seconds it powers TV On. LED turns off ***
***The bug is that the above is true only if I move out of line of sight. If I try to back away from it -within line of sight - past the 90cm mark it stays in the LED on stage (as if it still senses something within 90cm)
This is true even if I back up 9ft ( which is ~274cm). That is 184cm beyond what, I believe I coded it for, and 124cm beyond the specs of the max distance of the device
The only way I can think to debug the issue is to get the data from the analogRead and distance conversion and put it onto a serial monitor to see what the ATtiny is seeing, but have tried a few different guides on how to do this but each time I don't get anything
Hopefully the bug is a coding issue that someone here can see in a matter of moments, but I feel it has deeper roots.
Appreciate any help.
Thanks.