2 Commits
10 changed files with 283 additions and 139 deletions

No files matched your search

+48 -2
View File
@@ -14,7 +14,16 @@ FireFly Solar is a small outdoor LED blinker inspired by the idea of an LED thro
During the day, the solar cell charges the energy storage. During the day, the solar cell charges the energy storage.
At night, the circuit wakes up and sends a simple Morse-style light signal. At night, the circuit wakes up and sends a simple Morse-style light signal.
The project is partly a small garden object, partly a low-power electronics experiment, and partly a design exercise for future DIY kits. ## About this Project
FireFly Solar is my **technology playground**. It is a small garden object, but its real purpose is to learn by building something complete. With it I learn about:
- **Circuit design at the edge**: in this case, as low power as possible
- **PCB design**
- **Weatherproof casing**
- **ATtiny programming**
Possible next technology step: everything about DIY SMD design and soldering.
## Project Goals ## Project Goals
@@ -24,6 +33,40 @@ The project is partly a small garden object, partly a low-power electronics expe
- Test mechanical concepts for outdoor 3D-printed parts - Test mechanical concepts for outdoor 3D-printed parts
- Learn what is needed to turn a small electronics project into a possible DIY kit - Learn what is needed to turn a small electronics project into a possible DIY kit
## Software
The firmware runs on an **ATtiny85** at 1 MHz (internal clock, ATTinyCore: `clock=1internal`, `millis=disabled`). The LED itself is used as the light sensor. When it is dark, the firefly sends a short Morse text ("TGO 26") about once a minute.
### Current Firmware version: v0.4 (2026-11-08)
Goal: lowest possible average current.
Changes vs v0.3:
- No `delay()` / `millis()`; Timer0 and Timer1 are gated off in PRR.
- The watchdog (interrupt mode) is the only timebase: Morse units (~96 ms), the sensing window and the 8 s sleeps. The CPU sleeps in power-down in between.
- Darkness sensing: the CPU sleeps in 16 ms steps while the LED junction discharges, instead of a busy `digitalRead()` loop. Bright light exits after the first step. `darknessThreshold` is replaced by `darkSteps`.
- The ADC is disabled before it is gated off in PRR; pins are set up before PRR.
- After a power-on or external reset, no blinking for `RECOVER_CYCLES` (about 16 min), so the supercap can recharge.
- `DEBUG_TEST` switch for bench testing: 8 s cycle, no recovery wait, short flash when the sketch decides "bright". Set it to 0 for the field.
- Optional `BOD_FUSE_ENABLED` (BOD off during sleep); unused with the BOD fuse off.
Tested: compiles with ATTinyCore and runs on hardware. Current draw is not yet measured.
## PCB
- Finished: a batch of 10 is assembled, tested and working.
- Latest adjustment: fine-tuned the resistors for the LED, and the 3.9 V Zener diode is confirmed safe avoid overcharging 4V supercap.
- Next version: the PCB should be a little shorter. The wiring space is a bit too tight now.
## Casing
Works basically as intended. Lessons for the next version:
- Better locking of the solar modules.
- The rope structure works, but building it is too complicated and takes a lot of nerves.
- Using material tension to secure the modules via rope was basically a good idea.
## Naming ## Naming
The English project name remains: The English project name remains:
@@ -39,9 +82,12 @@ The name roughly means **sun-disc firefly**. It keeps the solar theme, adds a sl
--- ---
## Contributing ## Contributing
PRs and issues welcome. Keep it simple. PRs and issues welcome. Keep it simple.
Photos of your build you send me go in `Documentation/gallery/` with a short caption and license notice. Photos of your build you send me go in `Documentation/gallery/` with a short caption and license notice.
--- ---
## Default license**: [CC-BY-NC-4.0](https://creativecommons.org/licenses/by-nc/4.0/) ## License
Default license: [CC-BY-NC-4.0](https://creativecommons.org/licenses/by-nc/4.0/)
@@ -6,19 +6,33 @@
Project definitions, sources Project definitions, sources
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
Version: 0.3 - ATTiny85, 1 MHz, BOD fuse disabled Version: 0.4 - ATTiny85, 1 MHz, BOD fuse disabled
gitea : https://gitea.togo-lab.io/tgohle/0001-FireFly gitea : https://gitea.togo-lab.io/tgohle/0001-FireFly
Date : 2026-06-14 Date : 2026-11-08
Key changes Version 0.3: Key changes Version 0.4 (goal: lowest possible average current):
- Removed unnecessary ADC enable/disable from loop() - No delay(), no millis(): Timer0 and Timer1 are not needed any more and
- Disabled ADC and analog comparator in setup() are switched off in PRR.
- Added INPUT_PULLUP for unused Arduino pins 0, 1, 2 will save power - ALL timing (Morse units, sensing window, 8 s sleep) is done by the watchdog
- Added safer watchdog setup with interrupt protection to save run near brownout in interrupt mode while the CPU is in POWER-DOWN. The CPU runs only for a
- Added wdt_reset() before sleep for cleaner 8 s timing few microseconds per wake-up. LED pins keep their state in power-down.
- Added lowercase-to-uppercase handling - Darkness sensing no longer polls digitalRead() in a busy loop (that was
- Unsupported characters are now ignored without adding fake timing gaps ~0.3-1 s awake per cycle). The LED junction is charged, then the CPU sleeps
in 16 ms steps and checks the pin: bright light exits after the first step.
- ADC is disabled BEFORE it is gated off in PRR (order matters).
- After a power-on / external reset the sketch waits RECOVER_CYCLES cycles
before it blinks again, so a nearly empty supercap can recharge first.
Default ~16 minutes, therefore added a debug option.
- Optional: BOD disable during sleep (only useful if BOD fuse is enabled).
Not tested yet.
- Field Test: After a sunny day in Winter, outdoor -1 ... 8°C, with a payload
of 10 signs) it blinks for >> 12h.
Timing note: the watchdog oscillator is not precise (changes with Vcc and
temperature). All Morse timing comes from the same clock, so dit/dah/gap
ratios stay correct; only the absolute speed drifts a little.
The HW actual allowes 5V and 3.3V, standard is 3.3V. So don't expec exact timing.
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
@@ -60,6 +74,12 @@ Inspired by Karl Lunt's FireFly project:
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <string.h> #include <string.h>
// ---------------------------------------------------------------------------
// DEBUG_TEST 1 = bench testing: no reset-recovery wait, a blink attempt every
// 8 s, and a short flash when the sketch thinks it is BRIGHT.
// SET TO 0 FOR THE FIELD (48 s cycle, 16 min recovery wait after a reset).
#define DEBUG_TEST 0
#ifndef cbi #ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif #endif
@@ -68,16 +88,55 @@ Inspired by Karl Lunt's FireFly project:
#endif #endif
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Timing: unit length in ms. // Watchdog timeout codes (nominal, at ~5 V; real values vary with Vcc/temp):
// At 1 MHz, delay() is accurate when F_CPU=1000000L is set in boards.txt. // actual HW uses 3.3 (standard) or 5V (for blue LED experimental setup)
// 100 ms gives readable optical Morse; raise to 150 ms if readability is poor. // so don't expect exact timing)
#define unitLength 100 // 0=16ms 1=32ms 2=64ms 3=128ms 4=250ms 5=500ms
// 6=1s 7=2s 8=4s 9=8s
//
// One Morse unit = UNIT_WDT_A + UNIT_WDT_B -> 64 ms + 32 ms = ~96 ms
// A=3, B=0 -> ~144 ms (easier to read, more LED time)
// A=3, B=0xFF -> ~128 ms
// A=2, B=0xFF -> ~64 ms (fast, less LED time, harder to read by eye)
// Use 0xFF for B to skip the second sleep.
#define UNIT_WDT_A 2
#define UNIT_WDT_B 1
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Sleep interval. // Sleep interval between two sensing/blink attempts: sleepCycles x 8 s.
// Watchdog setup uses 8 s. For final use, change sleepCycles from 4 to 6 // 6 x 8 s = 48 s. Goal ~ 1 blink/min.
// for about 32s - 48s between sensing/blinking activations. Goal ~ 1 blink/min #if DEBUG_TEST
const uint8_t sleepCycles = 6; const uint8_t sleepCycles = 1;
#else
const uint8_t sleepCycles = 5;
#endif
// ---------------------------------------------------------------------------
// Darkness window in 16 ms steps (nominal).
// After charging the LED junction the CPU sleeps step by step. If the pin
// reads LOW within the window the LED discharged quickly = bright = no blink.
// Still HIGH after the full window = dark = blink.
// Longer window = triggers in brighter conditions (like the old threshold).
// The window costs almost no energy (CPU sleeps), so it is only a threshold.
// Calibrate at real dusk. Old threshold 17000 loops: measure the old
// sensDarkness() time with micros() at your dusk level and divide it by 16 ms.
const uint8_t darkSteps = 40; // ~640 ms
// ---------------------------------------------------------------------------
// After a power-on / external reset (e.g. supercap was empty, DC/DC restart)
// do not blink for this many cycles (x ~48 s) so the supercap can recharge.
// 20 -> ~16 min. Set to 0 while testing/uploading (upload = external reset).
#if DEBUG_TEST
#define RECOVER_CYCLES 0
#else
#define RECOVER_CYCLES 20
#endif
// ---------------------------------------------------------------------------
// Set to 1 only if the BOD fuse is enabled (e.g. hfuse 0xDE = 1.8 V).
// Then BOD is switched off during power-down to save its ~20 uA.
// With BOD fuse disabled this has no effect, leave it 0.
#define BOD_FUSE_ENABLED 0
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// LED pin definitions (N-side = cathode, P-side = anode for sensing/driving). // LED pin definitions (N-side = cathode, P-side = anode for sensing/driving).
@@ -95,28 +154,25 @@ const uint8_t sleepCycles = 6;
// ATTiny85 has 512 bytes SRAM; this keeps the Morse text in flash. // ATTiny85 has 512 bytes SRAM; this keeps the Morse text in flash.
// Only uppercase letters, digits, spaces, and the special chars in the switch // Only uppercase letters, digits, spaces, and the special chars in the switch
// below are emitted. Lowercase letters are converted to uppercase. // below are emitted. Lowercase letters are converted to uppercase.
// Test setup: 20 x "0" because 0 = "-----" gives maximum LED ON time for test. // Shorter text = less LED time = less energy.
// shorter text will better, more text will cost more power. const char morseText[] PROGMEM = "TOGO-LAB.IO FIREFLY";
const char morseText[] PROGMEM = "TGO 26"; // Ruler: 0....0....1....1....2
// Ruler: 0....0....1...1....2 // Ruler: 01...5....0....5....0
// Ruler: 0....5....0...5....0
// ---------------------------------------------------------------------------
// Darkness threshold.
// Higher value = triggers in brighter conditions.
// Best calibrated at actual dusk/dawn with the chosen LED type.
const unsigned int darknessThreshold = 17000;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Watchdog interrupt flag — volatile because it is written in an ISR. // Watchdog interrupt flag - volatile because it is written in an ISR.
volatile bool f_wdt = true; volatile bool f_wdt = false;
// Remaining cycles without blinking after a reset.
static uint8_t recoverCycles = 0;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Forward declarations. // Forward declarations.
void setup_watchdog(uint8_t ii); static void sleepWdt(uint8_t ii);
void system_sleep(); static void waitUnits(uint8_t n);
void configureUnusedPins(); void configureUnusedPins();
void releaseLedPins(int LED_N, int LED_P); void releaseLedPins(int LED_N, int LED_P);
unsigned int sensDarkness(int LED_N, int LED_P); bool isDark(int LED_N, int LED_P);
void morse(int LED_N, int LED_P); void morse(int LED_N, int LED_P);
void dit(int LED_P); void dit(int LED_P);
void dah(int LED_P); void dah(int LED_P);
@@ -126,22 +182,28 @@ void dah(int LED_P);
// =========================================================================== // ===========================================================================
void setup() void setup()
{ {
// Disable unused peripherals immediately to save power. // Remember why we restarted, then clear the flags.
// PRTIM1, PRUSI: unused, safe to gate off. uint8_t resetCause = MCUSR;
// PRADC: ADC is not used; LED sensing is done with digitalRead(). MCUSR = 0;
// PRTIM0: must stay ON while awake because delay() depends on Timer0. if (resetCause & ((1 << PORF) | (1 << BORF) | (1 << EXTRF))) {
PRR = (1 << PRTIM1) | (1 << PRUSI) | (1 << PRADC); recoverCycles = RECOVER_CYCLES;
}
// ADC off. It is not needed for digitalRead()-based LED sensing.
cbi(ADCSRA, ADEN);
// Analog comparator off. Saves a little sleep current.
ACSR |= (1 << ACD);
// Pins first (while the Arduino core can still reach all timer registers
// for its turnOffPWM() handling in digitalWrite()).
configureUnusedPins(); configureUnusedPins();
releaseLedPins(LED1_N_SIDE, LED1_P_SIDE); releaseLedPins(LED1_N_SIDE, LED1_P_SIDE);
setup_watchdog(9); // 8-second watchdog interval. // ADC off FIRST, then gate its clock. With PRADC set, ADC register
// writes are ignored, so the order matters.
cbi(ADCSRA, ADEN);
// Analog comparator off.
ACSR |= (1 << ACD);
// Power reduction: ADC, USI, Timer0, Timer1 all off.
// Nothing in this sketch uses them: no delay(), no millis(), no analogWrite().
PRR = (1 << PRADC) | (1 << PRUSI) | (1 << PRTIM0) | (1 << PRTIM1);
} }
// =========================================================================== // ===========================================================================
@@ -149,22 +211,29 @@ void setup()
// =========================================================================== // ===========================================================================
void loop() void loop()
{ {
if (f_wdt) { if (recoverCycles > 0) {
f_wdt = false; recoverCycles--;
} else if (isDark(LED1_N_SIDE, LED1_P_SIDE)) {
if (sensDarkness(LED1_N_SIDE, LED1_P_SIDE) > darknessThreshold) {
morse(LED1_N_SIDE, LED1_P_SIDE); morse(LED1_N_SIDE, LED1_P_SIDE);
} }
#if DEBUG_TEST
else {
// Sketch decided "bright": one short ~128 ms flash so you can see it.
pinMode(LED1_N_SIDE, OUTPUT);
pinMode(LED1_P_SIDE, OUTPUT);
digitalWrite(LED1_N_SIDE, LOW);
digitalWrite(LED1_P_SIDE, HIGH);
sleepWdt(3);
digitalWrite(LED1_P_SIDE, LOW);
}
#endif
// Return LED pins to high-Z before sleeping. // Return LED pins to high-Z before sleeping.
// Internal pullups stay disabled for the LED pins. // Internal pullups stay disabled for the LED pins.
releaseLedPins(LED1_N_SIDE, LED1_P_SIDE); releaseLedPins(LED1_N_SIDE, LED1_P_SIDE);
}
// Test setup: 1 x 8 s sleep.
// Final setup: set sleepCycles = 4 for about 32 s.
for (uint8_t i = 0; i < sleepCycles; i++) { for (uint8_t i = 0; i < sleepCycles; i++) {
system_sleep(); sleepWdt(9); // 8 s each
} }
} }
@@ -188,87 +257,102 @@ void releaseLedPins(int LED_N, int LED_P)
} }
// =========================================================================== // ===========================================================================
// Sleep helpers // Sleep helpers (watchdog = only timebase)
// =========================================================================== // ===========================================================================
void system_sleep() ISR(WDT_vect)
{ {
// Reset watchdog counter so each sleep cycle starts with a fresh interval. f_wdt = true;
wdt_reset();
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
// Atomic sleep entry pattern.
// After sei(), AVR executes the next instruction before servicing interrupts,
// so sleep_cpu() is not skipped by a just-pending interrupt.
cli();
sleep_enable();
sei();
sleep_cpu();
// WDT interrupt wakes the CPU here.
sleep_disable();
} }
// Watchdog setup - ii selects timeout: // Sleep in POWER-DOWN until the watchdog interrupt fires after timeout code ii
// 0=16ms 1=32ms 2=64ms 3=128ms 4=250ms 5=500ms // (0=16 ms ... 9=8 s). Reconfigures the watchdog on every call, so the full
// 6=1s 7=2s 8=4s 9=8s // interval always starts fresh.
void setup_watchdog(uint8_t ii) static void sleepWdt(uint8_t ii)
{ {
if (ii > 9) ii = 9; if (ii > 9) ii = 9;
uint8_t bb = ii & 7; uint8_t bb = ii & 7;
if (ii > 7) bb |= (1 << WDP3); if (ii > 7) bb |= (1 << WDP3);
uint8_t oldSREG = SREG; // Interrupt-only mode (WDE = 0). WDIF written as 1 clears a stale flag.
cli(); const uint8_t cfg = bb | (1 << WDIE) | (1 << WDIF);
f_wdt = false;
cli();
wdt_reset(); wdt_reset();
MCUSR &= ~(1 << WDRF); MCUSR &= ~(1 << WDRF);
// Timed sequence: enable configuration change, then set interrupt-only WDT. // Timed sequence: the two writes must follow each other within 4 cycles.
WDTCR |= (1 << WDCE) | (1 << WDE); WDTCR = (1 << WDCE) | (1 << WDE);
WDTCR = bb | (1 << WDIE); WDTCR = cfg;
SREG = oldSREG; set_sleep_mode(SLEEP_MODE_PWR_DOWN);
// Atomic sleep entry: after sei() the next instruction (sleep_cpu) still
// executes before any interrupt is serviced, so the wake-up cannot be missed.
// Loop again if something else woke the CPU.
while (!f_wdt) {
sleep_enable();
#if BOD_FUSE_ENABLED
sleep_bod_disable();
#endif
sei();
sleep_cpu();
sleep_disable();
cli();
}
sei();
} }
ISR(WDT_vect) // Wait n Morse units in power-down.
static void waitUnits(uint8_t n)
{ {
f_wdt = true; while (n--) {
sleepWdt(UNIT_WDT_A);
#if UNIT_WDT_B != 0xFF
sleepWdt(UNIT_WDT_B);
#endif
}
} }
// =========================================================================== // ===========================================================================
// Light sensor // Light sensor
// =========================================================================== // ===========================================================================
// Returns a "darkness level": higher = darker. // Returns true if it is dark.
// Charges the LED junction capacitance, then times how long it takes to bleed // Charges the LED junction capacitance, then lets it bleed through the
// back through the reverse-biased LED until the input reads LOW. // reverse-biased LED while the CPU sleeps. Checks the pin every ~16 ms.
// ~30000 = pitch black, ~0 = bright light // LOW within the window -> bright (discharged fast)
unsigned int sensDarkness(int LED_N, int LED_P) // still HIGH at the end -> dark
// In power-down the input buffer of the floating pin is disabled by hardware,
// so the slowly falling voltage causes no shoot-through current.
bool isDark(int LED_N, int LED_P)
{ {
unsigned int i;
// Charge the LED junction capacitance. // Charge the LED junction capacitance.
pinMode(LED_N, OUTPUT); pinMode(LED_N, OUTPUT);
pinMode(LED_P, OUTPUT); pinMode(LED_P, OUTPUT);
digitalWrite(LED_N, HIGH); digitalWrite(LED_N, HIGH);
digitalWrite(LED_P, LOW); digitalWrite(LED_P, LOW);
// Let the N-side float and measure bleed-down time. // Let the N-side float (no pullup) and measure bleed-down time.
pinMode(LED_N, INPUT); pinMode(LED_N, INPUT);
digitalWrite(LED_N, LOW); // disable internal pullup digitalWrite(LED_N, LOW);
for (i = 0; i < 30000; i++) { bool dark = true;
if (digitalRead(LED_N) == LOW) break; for (uint8_t k = 0; k < darkSteps; k++) {
sleepWdt(0); // ~16 ms
if (digitalRead(LED_N) == LOW) {
dark = false; // bright: stop early
break;
}
} }
// Clean up after sensing: both LED pins low, then caller releases them. // Clean up after sensing: both LED pins low, caller releases them.
pinMode(LED_N, OUTPUT); pinMode(LED_N, OUTPUT);
digitalWrite(LED_N, LOW); digitalWrite(LED_N, LOW);
pinMode(LED_P, OUTPUT); pinMode(LED_P, OUTPUT);
digitalWrite(LED_P, LOW); digitalWrite(LED_P, LOW);
return i; return dark;
} }
// =========================================================================== // ===========================================================================
@@ -277,17 +361,17 @@ unsigned int sensDarkness(int LED_N, int LED_P)
void dit(int LED_P) void dit(int LED_P)
{ {
digitalWrite(LED_P, HIGH); digitalWrite(LED_P, HIGH);
delay(unitLength); waitUnits(1);
digitalWrite(LED_P, LOW); digitalWrite(LED_P, LOW);
delay(unitLength); waitUnits(1);
} }
void dah(int LED_P) void dah(int LED_P)
{ {
digitalWrite(LED_P, HIGH); digitalWrite(LED_P, HIGH);
delay(unitLength * 3); waitUnits(3);
digitalWrite(LED_P, LOW); digitalWrite(LED_P, LOW);
delay(unitLength); waitUnits(1);
} }
// =========================================================================== // ===========================================================================
@@ -371,7 +455,7 @@ void morse(int LED_N, int LED_P)
// Previous symbol already ended with 1 unit OFF and then received the // Previous symbol already ended with 1 unit OFF and then received the
// normal 2 unit character gap. Add 4 units here -> total word gap 7 units. // normal 2 unit character gap. Add 4 units here -> total word gap 7 units.
case ' ': case ' ':
delay(unitLength * 4); waitUnits(4);
break; break;
// Unsupported chars are ignored without adding an artificial gap. // Unsupported chars are ignored without adding an artificial gap.
@@ -382,7 +466,7 @@ void morse(int LED_N, int LED_P)
// Inter-character gap: 3 units total. // Inter-character gap: 3 units total.
// dit()/dah() already trail 1 unit OFF, so add the remaining 2 units. // dit()/dah() already trail 1 unit OFF, so add the remaining 2 units.
if (symbolSent) { if (symbolSent) {
delay(unitLength * 2); waitUnits(2);
} }
} }
@@ -9,7 +9,7 @@
(paper "A4") (paper "A4")
(title_block (title_block
(title "日輪蛍 / Nichirin Hotaru / FireFly Solar") (title "日輪蛍 / Nichirin Hotaru / FireFly Solar")
(date "2026-07-02") (date "2026-09-27")
(rev "FireFly Sol 2") (rev "FireFly Sol 2")
(company "WWW: https://togo-lab.io") (company "WWW: https://togo-lab.io")
(comment 1 "Email: tgohle@togo-lab.io") (comment 1 "Email: tgohle@togo-lab.io")
@@ -2094,8 +2094,8 @@
) )
) )
) )
(property "Value" "3V6 1.3W" (property "Value" "3V9 1.3W"
(at 5.588 0.508 0) (at 5.5372 0.0508 0)
(layer "F.SilkS") (layer "F.SilkS")
(uuid "0961063d-f8b2-473d-ac71-4e9497f2e68d") (uuid "0961063d-f8b2-473d-ac71-4e9497f2e68d")
(effects (effects
@@ -9803,7 +9803,7 @@
(justify left bottom) (justify left bottom)
) )
) )
(gr_text "#0001 日輪蛍\nNichirin Hotaru\n\nFireFly Solar\n\ntogo-lab.io\n2026 V 1.0" (gr_text "#0001 日輪蛍\nNichirin Hotaru\n\nFireFly Solar\n\ntogo-lab.io\n2026 V 3.0"
(at 135.382 84.709 0) (at 135.382 84.709 0)
(layer "B.SilkS") (layer "B.SilkS")
(uuid "88b0a397-e4a2-4145-86f6-0fa60b4a4bd9") (uuid "88b0a397-e4a2-4145-86f6-0fa60b4a4bd9")
@@ -9816,7 +9816,7 @@
) )
(justify bottom mirror) (justify bottom mirror)
) )
(render_cache "#0001 日輪蛍\nNichirin Hotaru\n\nFireFly Solar\n\ntogo-lab.io\n2026 V 1.0" (render_cache "#0001 日輪蛍\nNichirin Hotaru\n\nFireFly Solar\n\ntogo-lab.io\n2026 V 3.0"
0 0
(polygon (polygon
(pts (pts
@@ -11359,25 +11359,37 @@
) )
(polygon (polygon
(pts (pts
(xy 132.305492 83.4953) (xy 132.314285 83.529005) (xy 132.327181 83.570771) (xy 132.3407 83.588268) (xy 132.102893 83.703028) (xy 132.149778 83.746548) (xy 132.206794 83.779305) (xy 132.328427 83.832941)
(xy 132.364843 83.601472) (xy 132.374882 83.627484) (xy 132.393493 83.659577) (xy 132.414229 83.697752) (xy 132.388647 83.886206) (xy 132.456068 83.932739) (xy 132.59045 84.022937) (xy 132.581218 84.057229)
(xy 132.420316 83.715223) (xy 132.419871 83.727721) (xy 132.539672 83.915739) (xy 132.597455 84.01795) (xy 132.578067 84.085806) (xy 132.560533 84.091707) (xy 132.535056 84.110498) (xy 132.490653 84.159298)
(xy 132.648775 84.119511) (xy 132.702436 84.223652) (xy 132.765719 84.333834) (xy 132.835364 84.438492) (xy 132.475747 84.183918) (xy 132.47336 84.196008) (xy 132.449373 84.212983) (xy 132.422069 84.248251)
(xy 132.905304 84.523757) (xy 132.921099 84.519152) (xy 132.927945 84.505879) (xy 132.930583 84.472759) (xy 132.3773 84.33127) (xy 132.349383 84.393991) (xy 132.351509 84.41993) (xy 132.368946 84.441325)
(xy 132.930583 84.463234) (xy 132.921649 84.459409) (xy 132.904718 84.434877) (xy 132.86559 84.354351) (xy 132.392561 84.452427) (xy 132.407708 84.4477) (xy 132.563852 84.475324) (xy 132.649371 84.483492)
(xy 132.819281 84.247006) (xy 132.775464 84.138782) (xy 132.742931 84.054225) (xy 132.736337 84.049975) (xy 132.737216 84.486242) (xy 132.824442 84.483972) (xy 132.905524 84.477376) (xy 132.983273 84.465188)
(xy 132.722195 84.045286) (xy 132.720713 84.024039) (xy 132.707394 83.987034) (xy 132.669219 83.909438) (xy 133.050457 84.447773) (xy 133.029476 84.436084) (xy 132.990813 84.423227) (xy 132.894752 84.402418)
(xy 132.642474 83.857707) (xy 132.630824 83.820924) (xy 132.621518 83.816277) (xy 132.610161 83.796524) (xy 132.793782 84.386884) (xy 132.726298 84.379043) (xy 132.70776 84.379043) (xy 132.644965 84.379043)
(xy 132.591989 83.742083) (xy 132.581804 83.699658) (xy 132.575796 83.695408) (xy 132.556012 83.679801) (xy 132.608563 84.376692) (xy 132.577994 84.370104) (xy 132.554249 84.357412) (xy 132.545387 84.340722)
(xy 132.539892 83.660163) (xy 132.539879 83.650038) (xy 132.55037 83.637742) (xy 132.542195 83.624458) (xy 132.546275 84.326793) (xy 132.55799 84.300861) (xy 132.596312 84.241803) (xy 132.639836 84.184944)
(xy 132.531099 83.618251) (xy 132.521226 83.61234) (xy 132.51791 83.601106) (xy 132.536359 83.590858) (xy 132.669145 84.151458) (xy 132.690748 84.131855) (xy 132.71626 84.115554) (xy 132.738221 84.095772)
(xy 132.567589 83.58352) (xy 132.640203 83.578831) (xy 132.706588 83.584546) (xy 132.730403 83.592341) (xy 132.752383 84.061552) (xy 132.741386 84.049543) (xy 132.736117 84.034221) (xy 132.733625 84.003813)
(xy 132.737655 83.599787) (xy 132.75728 83.608464) (xy 132.778354 83.608725) (xy 132.802575 83.599787) (xy 132.733625 83.997732) (xy 132.693353 83.964706) (xy 132.644452 83.931493) (xy 132.543556 83.868551)
(xy 132.860681 83.559926) (xy 132.849836 83.536552) (xy 132.849201 83.52133) (xy 132.857603 83.503286) (xy 132.459145 83.81008) (xy 132.429495 83.781769) (xy 132.417307 83.760327) (xy 132.367921 83.741716)
(xy 132.815325 83.490317) (xy 132.795016 83.480533) (xy 132.787481 83.462107) (xy 132.703344 83.436625) (xy 132.345324 83.728468) (xy 132.330258 83.714166) (xy 132.322976 83.697839) (xy 132.326815 83.681046)
(xy 132.621738 83.419389) (xy 132.537841 83.412686) (xy 132.441267 83.419535) (xy 132.431971 83.428417) (xy 132.342529 83.664113) (xy 132.370339 83.656207) (xy 132.402194 83.650219) (xy 132.435112 83.636643)
(xy 132.421996 83.431113) (xy 132.397523 83.427742) (xy 132.384041 83.42613) (xy 132.370046 83.424445) (xy 132.446933 83.626784) (xy 132.451891 83.617226) (xy 132.457379 83.609352) (xy 132.471748 83.605062)
(xy 132.34691 83.435561) (xy 132.330771 83.45456) (xy 132.517925 83.578938) (xy 132.579166 83.558094) (xy 132.645633 83.544235) (xy 132.718092 83.535526)
(xy 132.861487 83.529591) (xy 132.929014 83.531692) (xy 132.983779 83.537431) (xy 133.032407 83.546654)
(xy 133.058444 83.55509) (xy 133.065185 83.567766) (xy 133.077348 83.569818) (xy 133.089658 83.569818)
(xy 133.106584 83.57568) (xy 133.122645 83.541587) (xy 133.120872 83.51926) (xy 133.097572 83.482477)
(xy 133.082184 83.462913) (xy 133.079347 83.453219) (xy 133.081818 83.442836) (xy 133.057696 83.422252)
(xy 133.038514 83.414993) (xy 132.998214 83.41404) (xy 132.968538 83.415725) (xy 132.954304 83.412354)
(xy 132.937031 83.400484) (xy 132.89336 83.402243) (xy 132.840531 83.402243) (xy 132.737143 83.402243)
(xy 132.624009 83.409131) (xy 132.612808 83.425319) (xy 132.608768 83.427376) (xy 132.600342 83.421587)
(xy 132.587006 83.412355) (xy 132.579428 83.414676) (xy 132.566197 83.431113) (xy 132.554405 83.425924)
(xy 132.527362 83.426643) (xy 132.461856 83.441884) (xy 132.394519 83.463719) (xy 132.343594 83.481451)
(xy 132.341689 83.483429) (xy 132.27567 83.52351) (xy 132.205621 83.563956) (xy 132.176091 83.592213)
(xy 132.153671 83.63188) (xy 132.140744 83.632576) (xy 132.132348 83.641186) (xy 132.12253 83.667564)
(xy 132.115203 83.687934)
) )
) )
(polygon (polygon
@@ -379,7 +379,7 @@
"internal_id": "", "internal_id": "",
"mfg": "", "mfg": "",
"mpn": "", "mpn": "",
"sch_revision": "2" "sch_revision": "3"
}, },
"layer_pairs": [], "layer_pairs": [],
"layer_presets": [], "layer_presets": [],
@@ -665,6 +665,7 @@
"netlist": "", "netlist": "",
"plot": "", "plot": "",
"specctra_dsn": "", "specctra_dsn": "",
"step": "",
"vrml": "" "vrml": ""
}, },
"page_layout_descr_file": "" "page_layout_descr_file": ""
@@ -6,8 +6,8 @@
(paper "A4") (paper "A4")
(title_block (title_block
(title "日輪蛍 / Nichirin Hotaru / FireFly Solar") (title "日輪蛍 / Nichirin Hotaru / FireFly Solar")
(date "2026-07-02") (date "2026-09-27")
(rev "2") (rev "3")
(company "Tōgō Lab / 塔郷研究所") (company "Tōgō Lab / 塔郷研究所")
(comment 1 "WWW: https://togo-lab.io") (comment 1 "WWW: https://togo-lab.io")
(comment 2 "Email: tgohle@togo-lab.io") (comment 2 "Email: tgohle@togo-lab.io")
@@ -2123,9 +2123,9 @@
(embedded_fonts no) (embedded_fonts no)
) )
) )
(text "R2 value depends on volage Setting and D6 LED Type:\n\n3.3 V: - RED 470 Ω (tested)\n - GREEN, LOW-VF 470 Ω (not tested)\n - YELLOW, LOW-VF 470 Ω (not tested)\n\n5.0 V: - RED 560 Ω tested, but 5V not recommended" (text "R2 value depends on volage Setting and D6 LED Type.\nOnly tested this settings:\n\n3.3 V:\n- RED 640 Ω (~ 2,2 mA tested,)\n- GREEN 330 Ω (~ 2,2 mA tested, very bright!)\n\n"
(exclude_from_sim no) (exclude_from_sim no)
(at 196.342 59.69 0) (at 219.964 58.42 0)
(effects (effects
(font (font
(size 1.27 1.27) (size 1.27 1.27)
@@ -2144,9 +2144,9 @@
) )
(uuid "0bf54ea3-f975-4977-80ee-b53880b5df6d") (uuid "0bf54ea3-f975-4977-80ee-b53880b5df6d")
) )
(text "I use 4V SuperCap 50F.\nThis needs protection for overvoltage \nfrom Solar panels therefore Z-Diode\nwith 3.6V.\nDuring a bright Day most energy is\nused by R1, therefore 2W typ.\nC1 = SuperCap should load < 1h." (text "I use 4V SuperCap 50F.\nThis needs protection for overvoltage \nfrom solar panels therefore Z-Diode\nwith 3.6 - 3.9V. (depending on solar panel)\nDuring a bright Day most energy is\nused by R1, therefore 2W typ.\nC1 = SuperCap should load 2..3 h."
(exclude_from_sim no) (exclude_from_sim no)
(at 76.2 69.342 0) (at 76.708 63.246 0)
(effects (effects
(font (font
(size 1.27 1.27) (size 1.27 1.27)
@@ -2155,13 +2155,14 @@
) )
(uuid "151e3e93-9403-408a-bca5-e165542b5719") (uuid "151e3e93-9403-408a-bca5-e165542b5719")
) )
(text "C6 RESET, optional" (text "C6 RESET, optional\n\nin V1 not used, works without"
(exclude_from_sim no) (exclude_from_sim no)
(at 263.398 105.156 0) (at 254.762 108.966 0)
(effects (effects
(font (font
(size 1.27 1.27) (size 1.27 1.27)
) )
(justify left)
) )
(uuid "1bf5fdfb-548f-4ff1-9dbf-73a875269c83") (uuid "1bf5fdfb-548f-4ff1-9dbf-73a875269c83")
) )
@@ -2176,9 +2177,9 @@
) )
(uuid "71b72fad-9748-4a7a-92a5-a4bc4876fb33") (uuid "71b72fad-9748-4a7a-92a5-a4bc4876fb33")
) )
(text "max 3x Solar Modules,\n5V Type with 60x60mm\n ~ 4.5 V and 10mA under real conditions\n will charge C1 in ~ 1.5h upt to 3.5V\n\nPin 1 = +\nPin 2 = -/GND\n" (text "max 3x Solar Modules,\n~ 5V Type with 60x60mm\n -> ~ 4.5 V and 10mA under real conditions\n will charge C1 in ~ 3h upt to > 3.5V\n\nPin 1 = +\nPin 2 = -/GND\n"
(exclude_from_sim no) (exclude_from_sim no)
(at 25.4 69.596 0) (at 25.908 63.5 0)
(effects (effects
(font (font
(size 1.27 1.27) (size 1.27 1.27)
@@ -4930,7 +4931,7 @@
(justify left) (justify left)
) )
) )
(property "Value" "BZV85-C3V6 1.3W" (property "Value" "BZV85-C3V9 1.3W"
(at 80.772 84.582 0) (at 80.772 84.582 0)
(show_name no) (show_name no)
(do_not_autoplace no) (do_not_autoplace no)
Binary file not shown.