combining pulse counters
-
yes but not interrupt based.
Have a look at button sketch
-
yes but not interrupt based.
Have a look at button sketch
-
No, use 1 nano, use interrupts for electricity and gas, and use digital input for water.
Unless you want everything interrupt based, then you will need 2 x nano (or a mega) -
Interrupt: whenever you input changes from low-to-high or high-to-low, the atmega will fire the method you told it to do.
Digital IO: if you want to know the state of the digital io, you have to constantly poll the io.Regarding 3 counters on 1 nano, have a look at 12 input pulse counter
-
Here is the difference in code.
Digital IO polling:
int inPin = 7; // pushbutton connected to digital pin 7 int val = 0; // variable to store the read value void setup() { pinMode(inPin, INPUT); // sets the digital pin 7 as input } void loop() { val = digitalRead(inPin); // read the input pin }Interrupt based:
const byte interruptPin = 2; volatile byte state = LOW; void setup() { pinMode(interruptPin, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE); } void loop() { // do whatever you want here } void blink() { // this gets called whenever the input changes state = !state; } -
Hello, a digital input allows you to read a digital signal value. You call "digitalRead" and then you get the current value of the pin.
An interrupt will ... interrupt your code to call the method you have associated to the interrupt. On atmega328 which is used by the nano you have only 2 external interrupts.
You could also use the pin change interrupts but it's much more complicated, and if you're not clear with the concept of the interrupt yet it's better to read and learn about it first.
Another solution is to use an arduino mega which has 6 external interrupts.Also, interrupt methods should execute as fast as possible, you should never have a serial.write inside an interrupt. Instead, set a flag, and check the flag in the loop method: if flag is set do the serial.write and reset the flag.
-
I managed to get it working. First issue was to get the Mega working with the mega.
I needed to change MyConfig.h:
#define MY_RF24_CS_PIN 53I used CE on pin 9 (and not 40) and further more:

My sketch:
// Enable debug prints #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 #include <MySensors.h> // electricity #define DIGITAL_INPUT_SENSOR_e 18 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_e 1000 // Nummber of blinks per KWH of your meeter #define SLEEP_MODE false // Watt-value can only be reported when sleep mode is false. #define MAX_WATT_e 10000 // Max watt value to report. This filetrs outliers. #define CHILD_ID_e 1 // Id of the sensor child // Water #define DIGITAL_INPUT_SENSOR_w 19 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_w 1000 // Nummber of blinks per m3 of your meter (One rotation/liter) #define MAX_FLOW_w 40 // Max flow (l/min) value to report. This filters outliers. #define CHILD_ID_w 2 // Id of the sensor child // Gas #define DIGITAL_INPUT_SENSOR_g 20 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_g 1000 // Nummber of blinks per m3 of your meter (One rotation/liter) #define MAX_FLOW_g 40 // Max flow (l/min) value to report. This filters outliers. #define CHILD_ID_g 3 // Id of the sensor child unsigned long SEND_FREQUENCY = 30000; // Minimum time between send (in milliseconds). We don't want to spam the gateway. //unsigned long SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway. double ppwh = ((double)PULSE_FACTOR_e)/1000; // Pulses per watt hour double pplw = ((double)PULSE_FACTOR_w)/1000; double pplg = ((double)PULSE_FACTOR_g)/1000; //electricity bool pcReceived_e = false; volatile unsigned long pulseCount_e = 0; volatile unsigned long lastBlink_e = 0; volatile unsigned long watt = 0; unsigned long oldPulseCount_e = 0; unsigned long oldWatt = 0; double oldKwh; unsigned long lastSend_e; // water volatile unsigned long pulseCount_w = 0; volatile unsigned long lastBlink_w = 0; volatile double flow_w = 0; bool pcReceived_w = false; unsigned long oldPulseCount_w = 0; unsigned long newBlink_w = 0; double oldflow_w = 0; double volume_w =0; double oldvolume_w =0; unsigned long lastSend_w =0; unsigned long lastPulse_w =0; // gas volatile unsigned long pulseCount_g = 0; volatile unsigned long lastBlink_g = 0; volatile double flow_g = 0; bool pcReceived_g = false; unsigned long oldPulseCount_g = 0; unsigned long newBlink_g = 0; double oldflow_g = 0; double volume_g =0; double oldvolume_g =0; unsigned long lastSend_g =0; unsigned long lastPulse_g =0; // electricity MyMessage wattMsg(CHILD_ID_e,V_WATT); MyMessage kwhMsg(CHILD_ID_e,V_KWH); MyMessage pcMsg(CHILD_ID_e,V_VAR1); // Water MyMessage waterflowMsg(CHILD_ID_w,V_FLOW); MyMessage watervolumeMsg(CHILD_ID_w,V_VOLUME); MyMessage waterlastCounterMsg(CHILD_ID_w,V_VAR2); // Gas MyMessage gasflowMsg(CHILD_ID_g,V_FLOW); MyMessage gasvolumeMsg(CHILD_ID_g,V_VOLUME); MyMessage gaslastCounterMsg(CHILD_ID_g,V_VAR3); void setup() { // Fetch last known pulse count value from gw request(CHILD_ID_e, V_VAR1); request(CHILD_ID_w, V_VAR2); request(CHILD_ID_g, V_VAR3); // Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output // If no pullup is used, the reported usage will be too high because of the floating pin pinMode(DIGITAL_INPUT_SENSOR_e,INPUT_PULLUP); pinMode(DIGITAL_INPUT_SENSOR_w,INPUT_PULLUP); pinMode(DIGITAL_INPUT_SENSOR_g,INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_e), onPulse_e, RISING); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_w), onPulse_w, RISING); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_g), onPulse_g, RISING); lastSend_e=millis(); lastSend_w=millis(); lastSend_g=millis(); } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Meterkast Marcel", "1.0"); // Register this device as power sensor present(CHILD_ID_e, S_POWER); present(CHILD_ID_w, S_WATER); present(CHILD_ID_g, S_GAS); } void loop() { unsigned long now = millis(); // Only send values at a maximum frequency or woken up from sleep bool sendTime = now - lastSend_e > SEND_FREQUENCY; if (pcReceived_e && (SLEEP_MODE || sendTime)) { // New watt value has been calculated if (!SLEEP_MODE && watt != oldWatt) { // Check that we dont get unresonable large watt value. // could hapen when long wraps or false interrupt triggered if (watt<((unsigned long)MAX_WATT_e)) { send(wattMsg.set(watt)); // Send watt value to gw } Serial.print("Watt:"); Serial.println(watt); oldWatt = watt; } // Pulse count has changed if (pulseCount_e != oldPulseCount_e) { send(pcMsg.set(pulseCount_e)); // Send pulse count value to gw double kwh = ((double)pulseCount_e/((double)PULSE_FACTOR_e)); oldPulseCount_e = pulseCount_e; if (kwh != oldKwh) { send(kwhMsg.set(kwh, 4)); // Send kwh value to gw oldKwh = kwh; } } lastSend_e = now; } else if (sendTime && !pcReceived_e) { // No count received. Try requesting it again request(CHILD_ID_e, V_VAR1); lastSend_e=now; } unsigned long currentTime = millis(); // Only send values at a maximum frequency or woken up from sleep if (SLEEP_MODE || (currentTime - lastSend_w > SEND_FREQUENCY)) { lastSend_w=currentTime; if (!pcReceived_w) { //Last Pulsecount not yet received from controller, request it again request(CHILD_ID_w, V_VAR2); return; } if (!SLEEP_MODE && flow_w != oldflow_w) { oldflow_w = flow_w; Serial.print("l/min:"); Serial.println(flow_w); // Check that we dont get unresonable large flow value. // could hapen when long wraps or false interrupt triggered if (flow_w<((unsigned long)MAX_FLOW_w)) { send(waterflowMsg.set(flow_w, 2)); // Send flow value to gw } } // No Pulse count received in 2min if(currentTime - lastPulse_w > 120000){ flow_w = 0; } // Pulse count has changed if ((pulseCount_w != oldPulseCount_w)||(!SLEEP_MODE)) { oldPulseCount_w = pulseCount_w; Serial.print("pulsecount_w:"); Serial.println(pulseCount_w); send(waterlastCounterMsg.set(pulseCount_w)); // Send pulsecount value to gw in VAR1 double volume_w = ((double)pulseCount_w/((double)PULSE_FACTOR_w)); if ((volume_w != oldvolume_w)||(!SLEEP_MODE)) { oldvolume_w = volume_w; Serial.print("volume_w:"); Serial.println(volume_w, 3); send(watervolumeMsg.set(volume_w, 3)); // Send volume value to gw } } } // Only send values at a maximum frequency or woken up from sleep if (SLEEP_MODE || (currentTime - lastSend_g > SEND_FREQUENCY)) { lastSend_g=currentTime; if (!pcReceived_g) { //Last Pulsecount not yet received from controller, request it again request(CHILD_ID_g, V_VAR3); return; } if (!SLEEP_MODE && flow_g != oldflow_g) { oldflow_g = flow_g; Serial.print("l/min:"); Serial.println(flow_g); // Check that we dont get unresonable large flow value. // could hapen when long wraps or false interrupt triggered if (flow_g<((unsigned long)MAX_FLOW_g)) { send(gasflowMsg.set(flow_g, 2)); // Send flow value to gw } } // No Pulse count received in 2min if(currentTime - lastPulse_g > 120000){ flow_g = 0; } // Pulse count has changed if ((pulseCount_g != oldPulseCount_g)||(!SLEEP_MODE)) { oldPulseCount_g = pulseCount_g; Serial.print("pulsecount_g:"); Serial.println(pulseCount_g); send(gaslastCounterMsg.set(pulseCount_g)); // Send pulsecount value to gw in VAR1 double volume_g = ((double)pulseCount_g/((double)PULSE_FACTOR_g)); if ((volume_g != oldvolume_g)||(!SLEEP_MODE)) { oldvolume_g = volume_g; Serial.print("volume_g:"); Serial.println(volume_g, 3); send(gasvolumeMsg.set(volume_g, 3)); // Send volume value to gw } } } if (SLEEP_MODE) { sleep(SEND_FREQUENCY); } } void receive(const MyMessage &message) { if (message.type==V_VAR1) { pulseCount_e = oldPulseCount_e = message.getLong(); Serial.print("Received last pulse count from gw_e:"); Serial.println(pulseCount_e); pcReceived_e = true; } if (message.type==V_VAR2) { unsigned long gwPulseCount_w=message.getULong(); pulseCount_w += gwPulseCount_w; flow_w=oldflow_w=0; Serial.print("Received last pulse count from gw_w:"); Serial.println(pulseCount_w); pcReceived_w = true; } if (message.type==V_VAR3) { unsigned long gwPulseCount_g=message.getULong(); pulseCount_g += gwPulseCount_g; flow_g=oldflow_g=0; Serial.print("Received last pulse count from gw_g:"); Serial.println(pulseCount_g); pcReceived_g = true; } } void onPulse_e() { if (!SLEEP_MODE) { unsigned long newBlink_e = micros(); unsigned long interval_e = newBlink_e-lastBlink_e; if (interval_e<10000L) { // Sometimes we get interrupt on RISING return; } watt = (3600000000.0 /interval_e) / ppwh; lastBlink_e = newBlink_e; } pulseCount_e++; } void onPulse_w() { if (!SLEEP_MODE) { unsigned long newBlink_w = micros(); unsigned long interval_w = newBlink_w-lastBlink_w; if (interval_w!=0) { lastPulse_w = millis(); if (interval_w<500000L) { // Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min) return; } flow_w = (60000000.0 /interval_w) / pplw; } lastBlink_w = newBlink_w; } pulseCount_w++; } void onPulse_g() { if (!SLEEP_MODE) { unsigned long newBlink_g = micros(); unsigned long interval_g = newBlink_g-lastBlink_g; if (interval_g!=0) { lastPulse_g = millis(); if (interval_g<500000L) { // Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min) return; } flow_g = (60000000.0 /interval_g) / pplg; } lastBlink_g = newBlink_g; } pulseCount_g++; }I still got one issue; my led on the meter does not give enough light to have a n interrupt. does anybody have a suggestion how to get the interrupt?
-
I managed to get it working. First issue was to get the Mega working with the mega.
I needed to change MyConfig.h:
#define MY_RF24_CS_PIN 53I used CE on pin 9 (and not 40) and further more:

My sketch:
// Enable debug prints #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 #include <MySensors.h> // electricity #define DIGITAL_INPUT_SENSOR_e 18 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_e 1000 // Nummber of blinks per KWH of your meeter #define SLEEP_MODE false // Watt-value can only be reported when sleep mode is false. #define MAX_WATT_e 10000 // Max watt value to report. This filetrs outliers. #define CHILD_ID_e 1 // Id of the sensor child // Water #define DIGITAL_INPUT_SENSOR_w 19 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_w 1000 // Nummber of blinks per m3 of your meter (One rotation/liter) #define MAX_FLOW_w 40 // Max flow (l/min) value to report. This filters outliers. #define CHILD_ID_w 2 // Id of the sensor child // Gas #define DIGITAL_INPUT_SENSOR_g 20 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR_g 1000 // Nummber of blinks per m3 of your meter (One rotation/liter) #define MAX_FLOW_g 40 // Max flow (l/min) value to report. This filters outliers. #define CHILD_ID_g 3 // Id of the sensor child unsigned long SEND_FREQUENCY = 30000; // Minimum time between send (in milliseconds). We don't want to spam the gateway. //unsigned long SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway. double ppwh = ((double)PULSE_FACTOR_e)/1000; // Pulses per watt hour double pplw = ((double)PULSE_FACTOR_w)/1000; double pplg = ((double)PULSE_FACTOR_g)/1000; //electricity bool pcReceived_e = false; volatile unsigned long pulseCount_e = 0; volatile unsigned long lastBlink_e = 0; volatile unsigned long watt = 0; unsigned long oldPulseCount_e = 0; unsigned long oldWatt = 0; double oldKwh; unsigned long lastSend_e; // water volatile unsigned long pulseCount_w = 0; volatile unsigned long lastBlink_w = 0; volatile double flow_w = 0; bool pcReceived_w = false; unsigned long oldPulseCount_w = 0; unsigned long newBlink_w = 0; double oldflow_w = 0; double volume_w =0; double oldvolume_w =0; unsigned long lastSend_w =0; unsigned long lastPulse_w =0; // gas volatile unsigned long pulseCount_g = 0; volatile unsigned long lastBlink_g = 0; volatile double flow_g = 0; bool pcReceived_g = false; unsigned long oldPulseCount_g = 0; unsigned long newBlink_g = 0; double oldflow_g = 0; double volume_g =0; double oldvolume_g =0; unsigned long lastSend_g =0; unsigned long lastPulse_g =0; // electricity MyMessage wattMsg(CHILD_ID_e,V_WATT); MyMessage kwhMsg(CHILD_ID_e,V_KWH); MyMessage pcMsg(CHILD_ID_e,V_VAR1); // Water MyMessage waterflowMsg(CHILD_ID_w,V_FLOW); MyMessage watervolumeMsg(CHILD_ID_w,V_VOLUME); MyMessage waterlastCounterMsg(CHILD_ID_w,V_VAR2); // Gas MyMessage gasflowMsg(CHILD_ID_g,V_FLOW); MyMessage gasvolumeMsg(CHILD_ID_g,V_VOLUME); MyMessage gaslastCounterMsg(CHILD_ID_g,V_VAR3); void setup() { // Fetch last known pulse count value from gw request(CHILD_ID_e, V_VAR1); request(CHILD_ID_w, V_VAR2); request(CHILD_ID_g, V_VAR3); // Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output // If no pullup is used, the reported usage will be too high because of the floating pin pinMode(DIGITAL_INPUT_SENSOR_e,INPUT_PULLUP); pinMode(DIGITAL_INPUT_SENSOR_w,INPUT_PULLUP); pinMode(DIGITAL_INPUT_SENSOR_g,INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_e), onPulse_e, RISING); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_w), onPulse_w, RISING); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR_g), onPulse_g, RISING); lastSend_e=millis(); lastSend_w=millis(); lastSend_g=millis(); } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Meterkast Marcel", "1.0"); // Register this device as power sensor present(CHILD_ID_e, S_POWER); present(CHILD_ID_w, S_WATER); present(CHILD_ID_g, S_GAS); } void loop() { unsigned long now = millis(); // Only send values at a maximum frequency or woken up from sleep bool sendTime = now - lastSend_e > SEND_FREQUENCY; if (pcReceived_e && (SLEEP_MODE || sendTime)) { // New watt value has been calculated if (!SLEEP_MODE && watt != oldWatt) { // Check that we dont get unresonable large watt value. // could hapen when long wraps or false interrupt triggered if (watt<((unsigned long)MAX_WATT_e)) { send(wattMsg.set(watt)); // Send watt value to gw } Serial.print("Watt:"); Serial.println(watt); oldWatt = watt; } // Pulse count has changed if (pulseCount_e != oldPulseCount_e) { send(pcMsg.set(pulseCount_e)); // Send pulse count value to gw double kwh = ((double)pulseCount_e/((double)PULSE_FACTOR_e)); oldPulseCount_e = pulseCount_e; if (kwh != oldKwh) { send(kwhMsg.set(kwh, 4)); // Send kwh value to gw oldKwh = kwh; } } lastSend_e = now; } else if (sendTime && !pcReceived_e) { // No count received. Try requesting it again request(CHILD_ID_e, V_VAR1); lastSend_e=now; } unsigned long currentTime = millis(); // Only send values at a maximum frequency or woken up from sleep if (SLEEP_MODE || (currentTime - lastSend_w > SEND_FREQUENCY)) { lastSend_w=currentTime; if (!pcReceived_w) { //Last Pulsecount not yet received from controller, request it again request(CHILD_ID_w, V_VAR2); return; } if (!SLEEP_MODE && flow_w != oldflow_w) { oldflow_w = flow_w; Serial.print("l/min:"); Serial.println(flow_w); // Check that we dont get unresonable large flow value. // could hapen when long wraps or false interrupt triggered if (flow_w<((unsigned long)MAX_FLOW_w)) { send(waterflowMsg.set(flow_w, 2)); // Send flow value to gw } } // No Pulse count received in 2min if(currentTime - lastPulse_w > 120000){ flow_w = 0; } // Pulse count has changed if ((pulseCount_w != oldPulseCount_w)||(!SLEEP_MODE)) { oldPulseCount_w = pulseCount_w; Serial.print("pulsecount_w:"); Serial.println(pulseCount_w); send(waterlastCounterMsg.set(pulseCount_w)); // Send pulsecount value to gw in VAR1 double volume_w = ((double)pulseCount_w/((double)PULSE_FACTOR_w)); if ((volume_w != oldvolume_w)||(!SLEEP_MODE)) { oldvolume_w = volume_w; Serial.print("volume_w:"); Serial.println(volume_w, 3); send(watervolumeMsg.set(volume_w, 3)); // Send volume value to gw } } } // Only send values at a maximum frequency or woken up from sleep if (SLEEP_MODE || (currentTime - lastSend_g > SEND_FREQUENCY)) { lastSend_g=currentTime; if (!pcReceived_g) { //Last Pulsecount not yet received from controller, request it again request(CHILD_ID_g, V_VAR3); return; } if (!SLEEP_MODE && flow_g != oldflow_g) { oldflow_g = flow_g; Serial.print("l/min:"); Serial.println(flow_g); // Check that we dont get unresonable large flow value. // could hapen when long wraps or false interrupt triggered if (flow_g<((unsigned long)MAX_FLOW_g)) { send(gasflowMsg.set(flow_g, 2)); // Send flow value to gw } } // No Pulse count received in 2min if(currentTime - lastPulse_g > 120000){ flow_g = 0; } // Pulse count has changed if ((pulseCount_g != oldPulseCount_g)||(!SLEEP_MODE)) { oldPulseCount_g = pulseCount_g; Serial.print("pulsecount_g:"); Serial.println(pulseCount_g); send(gaslastCounterMsg.set(pulseCount_g)); // Send pulsecount value to gw in VAR1 double volume_g = ((double)pulseCount_g/((double)PULSE_FACTOR_g)); if ((volume_g != oldvolume_g)||(!SLEEP_MODE)) { oldvolume_g = volume_g; Serial.print("volume_g:"); Serial.println(volume_g, 3); send(gasvolumeMsg.set(volume_g, 3)); // Send volume value to gw } } } if (SLEEP_MODE) { sleep(SEND_FREQUENCY); } } void receive(const MyMessage &message) { if (message.type==V_VAR1) { pulseCount_e = oldPulseCount_e = message.getLong(); Serial.print("Received last pulse count from gw_e:"); Serial.println(pulseCount_e); pcReceived_e = true; } if (message.type==V_VAR2) { unsigned long gwPulseCount_w=message.getULong(); pulseCount_w += gwPulseCount_w; flow_w=oldflow_w=0; Serial.print("Received last pulse count from gw_w:"); Serial.println(pulseCount_w); pcReceived_w = true; } if (message.type==V_VAR3) { unsigned long gwPulseCount_g=message.getULong(); pulseCount_g += gwPulseCount_g; flow_g=oldflow_g=0; Serial.print("Received last pulse count from gw_g:"); Serial.println(pulseCount_g); pcReceived_g = true; } } void onPulse_e() { if (!SLEEP_MODE) { unsigned long newBlink_e = micros(); unsigned long interval_e = newBlink_e-lastBlink_e; if (interval_e<10000L) { // Sometimes we get interrupt on RISING return; } watt = (3600000000.0 /interval_e) / ppwh; lastBlink_e = newBlink_e; } pulseCount_e++; } void onPulse_w() { if (!SLEEP_MODE) { unsigned long newBlink_w = micros(); unsigned long interval_w = newBlink_w-lastBlink_w; if (interval_w!=0) { lastPulse_w = millis(); if (interval_w<500000L) { // Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min) return; } flow_w = (60000000.0 /interval_w) / pplw; } lastBlink_w = newBlink_w; } pulseCount_w++; } void onPulse_g() { if (!SLEEP_MODE) { unsigned long newBlink_g = micros(); unsigned long interval_g = newBlink_g-lastBlink_g; if (interval_g!=0) { lastPulse_g = millis(); if (interval_g<500000L) { // Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min) return; } flow_g = (60000000.0 /interval_g) / pplg; } lastBlink_g = newBlink_g; } pulseCount_g++; }I still got one issue; my led on the meter does not give enough light to have a n interrupt. does anybody have a suggestion how to get the interrupt?
@htca what are you using to detect the light? You mentioned a LDR in the first post. If that's what you are using, here are a few options:
- More light. See if you can get the ldr closer to the led and more directly pointing towards it. You might be able to focus the light by using a lens in front of the LDR.
- adjust the value of the pullup. (Don't use the built-in, add an external with a higher value instead - which value depends on your ldr. Measure the max and min resistance (led is off + led is on) and calculate what size the pullup should be)
- get a ldr with different resistance
-
I use this one:

I used earlier which I made myself, but on a raspberry pi. Reading out analogue, passed it through a ADC and fed it to the pi.
Now use the one above and linked it to the mega. Adjusting the resistance by the pot-meter will get me always on or always off.
-
I use this one:

I used earlier which I made myself, but on a raspberry pi. Reading out analogue, passed it through a ADC and fed it to the pi.
Now use the one above and linked it to the mega. Adjusting the resistance by the pot-meter will get me always on or always off.