Analoge AUX-input maken op een originele Anker Soundcore Motion Boom box

De originele versie van de ANKER Soundcore Motion Boom heeft alleen een Bluetooth-ingang, en dat is natuurlijk niet ideaal als je hem wilt gebruiken voor een instrument zoals een gitaar of keyboard.

Dus – na wat onderzoek op internet – vond ik een goede video over hoe je de Motion Boom uit elkaar haalt, en dat heb ik als EERSTE gedaan voordat ik aan dit bericht begon.

Om de AUX-IN aan te brengen, kun je de luidsprekers aan de voorkant het beste gewoon vast laten zitten met de 8 schroeven, in plaats van ze te verwijderen.

In de behuizing zit één hoofdprintplaat waarop in feite alles zit, behalve de bedieningsknoppen.

De bedieningsknoppen zijn via een platte, flexibele printkabel verbonden met de hoofdprintplaat.

De Bluetooth-antenne is via een standaard mini-coaxaansluiting verbonden met de hoofdprintplaat.

Aan de voorkant bevindt zich ook een afstandsbedieningsontvanger, die eveneens is aangesloten op de hoofdprintplaat, maar dan via een mini-connector met twee draden.

En de accu is via een 7-polige connector aangesloten op de hoofdprintplaat.

De hoofdprintplaat heeft een aantal functies die gemakkelijk op de printplaat te herkennen zijn:

Versterker,
Bluetooth,
Acculader,
En de bedieningsinterface.

Nadat ik de behuizing uit elkaar had gehaald, heb ik de hoofdprintplaat en de accu (in één stuk) eruit gehaald.

Vervolgens heb ik de accu van de hoofdprintplaat verwijderd, voornamelijk om de printplaat gemakkelijker te kunnen hanteren.

Uit voorzorg heb ik de batterijaansluiting losgekoppeld, behalve tijdens het testen. Gewoon om er zeker van te zijn dat er tijdens het proces niets beschadigd raakt.

Vervolgens:

heb ik de luidsprekers aangesloten,
de bedieningselementen aangesloten,
de batterij aangesloten,
het apparaat ingeschakeld,
en mijn telefoon via B aangesloten.

Vervolgens:

Ik heb de luidsprekers aangesloten
De bedieningselementen aangesloten
De accu aangesloten
Het apparaat ingeschakeld,
Mijn telefoon via Bluetooth aangesloten om wat muziek af te spelen
Mijn Hantek-oscilloscoop gebruikt om de geluidsleidingen ergens tussen de Bluetooth-module en de versterker te lokaliseren.

De signaalopnamepunten bevinden zich in de buurt waar de versterker staat.

Op de foto zijn deze soldeerverbindingen met de rode en groene draad duidelijk zichtbaar:

Wit is de aardingsdraad, van de USB-A GND naar de 3,5 mm-ingang.

Vervolgens heb ik de groene en rode draden via condensatoren van 100 V en 0,1 uF aan de 3,5 mm mini-jack-ingang gesoldeerd.

Ik heb de 3,5 mm mini-jack-ingang zo op de printplaat gelijmd dat hij net boven de USB-C-aansluiting uitsteekt. Ik heb het gat geboord, het groot genoeg gemaakt om er van buitenaf een mini-jack-stekker in te steken, en dat was het!

Ik heb ook alle soldeerverbindingen en de condensatoren vastgelijmd, zodat ze niet afbreken, aangezien dit apparaat bedoeld is om veel te worden gebruikt. Door bewegingen kunnen soldeerverbindingen namelijk losraken als je ze niet vastlijmt.

Vervolgens heb ik alles weer in elkaar gezet en klaar is Kees!

De BT-module schakelt na een paar minuten uit als er geen verbinding tot stand komt. Dit heeft geen enkele invloed op de AUX-ingang, dus je kunt de AUX IN gewoon blijven gebruiken, ook wanneer BT naar verbindingen zoekt.

Ik hoop dat dit je helpt! Groeten, Jan

Grote luchtkanaal objecten 3d-printen met ABS/ASA op mijn Voron 2.4-600

Zoals altijd wanneer ik iets echt goed wil doen, kost het even tijd…

De overgang naar warmtepomp zodat we geen gas meer nodig hebben is aardig gelukt met de installatie van een lucht-lucht warmtepomp installatie voor de begane grond.

We hebben de binnen-unit in de woonkamer, net naast de trap naar boven geplaatst zodat we later ook gemakkelijk een tweede binnen-unit kunnen maken op de eerste verdieping.

KOELEN EN VERWARMEN MET LUCHT MOGELIJK?

Maar misschien is er ook een andere manier om boven te koelen en vooral: te verwarmen.  Want de binnen-unit in de woonkamer is ruim bemeten en draait vrijwel altijd op de silent modus. Dat geldt zowel voor verwarmen als koelen.  Dus heb ik het plan opgevat om een deel van de output van de binnen-unit met een luchtsysteem naar de eerste verdieping te brengen en ook de retourstroom terug naar de circulatie-inlaat van de lucht bovenaan de binnen-unit te voeren.

LUCHT PICK-UP VOOR AIRCO-BINNENUNIT

Eerst heb ik de adapter voor de lucht pickup van de airco’s binnen-unit ontworpen.  Dit is voor zover ik heb kunnen ontdekken, niet standaard te koop. Omdat de luchtflap van de binnen-unit moet kunnen bewegen heb ik de lucht pick-up met een circulaire cutout met de bewegingsradius van die luchtflap ontworpen.

Mijn eerste ontwerp van de lucht pick-up past over de helft van de lucht-uitstroom opening aan de voorkant, onderzijde van de airco binnen-unit.   Dat is prima als je zowel in de woonkamer als boven wilt koelen of verarmen.

Wanneer je primair boven wilt koelen of verarmen en maar een klein deel beneden, heb ik een ontwerp gemaakt dat helemaal over de lucht uitstroom past.  Aan de onderkant, onder de beweegbare flap, blijft dan altijd nog een strook over waardoor lucht de woonkamer in stroomt.  Dat kan je zo laten maar dat kun je natuurlijk ook dichtmaken. Ik heb dat getest met een dunne strook plastic foam-schuim ertussen en dat werkt prima om geen lucht meer in de woonkamer te laten.

Zie onderstaand ontwerp van de lucht-pickup die over de gehele breedte van de luchtuitstroom gebruikt kan worden:

HOE GROTE DELEN IN ABS PRINTEN (MIJN MANIER)

Ik print dit soort grote delen met mijn grote Voron 2.4-600  en bovenstaande adapter heb ik diagonaal moeten printen vanwege de lengte. Deze Voron staat ingesteld voor ABS met een heated bed op 120 graden en de extruder staat ingesteld op 265 graden. De toolfan draait bij mij voor dit soort prints gewoon op 100%, ongeacht het feit dat ABS dat niet nodig schijnt te hebben. Het geeft me gewoon betere resultaten op deze manier.  Ik gebruik support met 87% overhang instelling met ‘tree’-instelling.   Alles wordt geprint met 100% infill maar lage wanddikte van 1.6mm en de nozzle die ik altijd gebruik voor deze prints is 0.8mm, layer height is 0.4mm en de printsnelheid 120mm/s, en wanneer ik met infill werk dus geen 100% infill, staat de snelheid van de infill op dezelfde snelheid als de gewone layersnelheid, dus 120mm/s.  O ja, ik heb alleen maar een brim nodig bij deze printen en ABS wanneer ik lange objecten print. Alles onder 10cm breedte en/of lengte kan gewoon zonder brim.  het hotbed is een 6mm alu plaat met daaronder een 750 Watt 600/600 230V silicon zelfklevende mat en erop een magneetplaat, ook zelfklevend, Bovenop zit een Tronxy steelsheet van 600x610mm met een bijzondere pei-laag: niet grof maar ook niet heel fijn. De pei is daarnaast dubbelzijdig  en het werkt perfect met ABS maar helemaal niet met PETG (blijft vastzitten, ook NA afkoelen) , EASY ABS en gemiddeld OK met PLA (niet veel hechting).

Het heeft heel wat tijd geduurd voordat ik voor deze printer (met Canbus head) de optimale instellingen voor dit type ABS heb gevonden. Ik draai nu met deze instellingen bijna alle soorten ABS, mits het echt normale ABS is. Ik heb wel eens zogenaamd EASY ABS geprobeerd maar door de lage vloeitemperatuur daarvan loopt dat niet lekker op deze Voron. Maar op mijn iBear, gewoon open in de omgevingslucht, draait dat EASY ABS perfect, op PETG instellingen. Wonderlijk maar ook wel prima!

LUCHTKANALEN INSTALLEREN

Het werk aan de luchtkanalen was allemaal toch wat meer puzzelen dan ik had gedacht: Natuurlijk eerst de gaten in de muur tussen woonkamer en trap maken.

Daarin heb ik doorvoerpassingen gemaakt met een kraag op de wand, zie bovenstaande foto. De luchtbuizen die ik gebruik zijn 110x55mm buitendiameter en deze schuiven door de muurkragen heen. Dat past heel netjes.

IN-LINE FANS: WELKE WERKT HET BEST?

Om de lucht naar boven te krijgen heb ik verschillende opties geprobeerd want de luchtstroom die vanuit de binnen-unit komt bleek onvoldoende druk te geven om nog een beetje luchtstroom in de slaapkamer over te houden.

Daarom heb ik geëxperimenteerd met eerst een 120mm in-line ventilator op 12 V en daarna één op 230 Volt.  De oplossing met 230 Volt ventilator in-line leek goed te werken maar de luchtstroom was toch nog onvoldoende om de koude lucht in de slaapkamer te brengen.

3D-ontworpen in-line fan adapter:

In wit ABS geprinte in-line adapter voor een 38mm dikke x120x120mm 230V AC fan unit
De in-line installatie van de 120mm 12V fan, dit werkte bijna helemaal niet. Met de 230V fan werkte het wel een beetje maar kwam de lucht door het afkoelen onderweg niet meer koud boven uit het einde van de ca. 7 meter lange luchtweg van de binnen-unit in de woonkamer naar slaapkamer.

Uiteindelijk heb ik een 50Watt in-line ventilator getest en dit werkte heel goed!

testopstelling met een 50 Watt in-line fan unit. Dit werkt heel goed zo!

MONTAGE LUCHTKANALEN EN FAN

Nu nog even alles op de goede plek monteren.

Het blijkt best lastig te zijn om in een bestaande woning met luchtkanalen aan de gang te gaan. Je wilt eigenlijk een weg zonder krappe bochten en den liefst met een 100-150mm ronde buis werken.

Daarom experimenteer ik eerst met deze 110/55 mm rechthoekige pijpen. Als alles werkt ga ik de kortste weg van binnen-unit naar de eerste en tweede verdieping bepalen, door de vloeren.

Als dat niet kan of geen kortere luchtweg oplevert, ga ik kijken of die tweede binnen-unit op de eerste verdieping kan worden gemonteerd…

Tijdelijke montage van de 110/55 luchtbuizen
Tijdelijke montage van de 110/55 luchtbuizen
Tijdelijke montage van de 110/55 luchtuitlaat in de slaapkamer

MAKEN OPHANGBEUGEL

MAKEN OPHANGBEUGEL VOOR IN-LINE 50 WATT FAN

De in-line 50-Watt ventilator unit heeft nogal wat aanpassingen nodig om in mijn tijdelijke installatie op te nemen. De in- en uitgangen zijn 98mm rond buitendiameter en daarvoor moet ik aanpassingen maken naar de bestaande buizen op een plek  waar dat niet in de weg zit.  Dat wordt dus mijn 3d printhok, tegen het plafond.

De montagebeugel voor de 50Watt in-line ventilatorunit heb ik alvast ontworpen en geprint:

Geprint is zwart ABS, 265 graden Celsius, 100% infill, wanddikte 6mm

 

125 mm airco slangadapter STL 3d-printbaar bestand voor standaard 42x375mm raam ventilatie-openingen

air exhaust VERY SHORT 121mm round for window klein achter beneden 375x42mm ventilation sleeve angled 20240607V15b DOWNLOAD STL

Doneer alsjeblieft $1 aan mijn paypal account als je (delen van) mijn ontwikkelde materialen gebruikt zodat ik leuke dingen kan blijven delen om te downloaden

The 125mm hose adapter just fits to print at 101% expansion setting on my Voron 300x300x300
Printed with 8% infill supports at 60 degrees angle support settings

arco hose adapter 125mm for window klein 2nd_3rd floor 275x42mm sleeve screw_on 20240612V16cDOWNLOAD STL

Doneer alsjeblieft $1 aan mijn paypal account als je (delen van) mijn ontwikkelde materialen gebruikt zodat ik leuke dingen kan blijven delen om te downloaden

Video van WhatsApp op 2024-06-14 om 08.36.55_1fb3b4bf

Ster en klok met Smart LEDs WS2812, Seeeduino xiaosamd21 cortex m0+ microcomputer, LDR control en DS3231 RTC nauwkeurige klok chip

De gebruikte onderdelen:  Meestal gebruik ik een AVR-type microcomputer zoals een Nano of een Mega maar bij een paar projecten met LEDS loop ik steeds vast op de beperking van geheugen. Daarom ben ik voor meer complexe projecten overgestapt op de Seeed studio XIAO SAMD21.  Lekker klein, snel en veel beschikbaar geheugen. Wel jammer dat ik alle code van de klok en dergelijke opnieuw moest maken, omdat de eerder gebruikte code alleen op AVR typen werkte.

De klok spreekt voor zich, de LDR gebruik ik voor automatisch  aanpassen van de lichtintensiteit, indien gewenst.  Alle belangrijke instellingen zijn via de USB-poort in te stellen.  De klok draait op UTC tijd en stelt zich zelf op het juiste moment in op de lokale zomer-of wintertijd.  Je moet dan eerst wel in de code de juiste regio selecteren.

Gemonteerd en heel compact:

En de montage van de 4 delen van de klok-LEDS in de 3d-geprinte ring waarin de delen met de LEDS worden gemonteerd:

En de werkende klok hier nog met een Arduino nano in plaats van een Seeeduino XIAO SAMD21 M0 en met een standaard klok voorbeeld programma:

https://jantecnl.synology.me/downloads/Neopixel_clock_with_3231_2020_12_15_OK.ino

Ronde klok WS2812 & Arduino nano

En meer gericht op effect dan op tijd:

Het coderen van een ster is iets complexer dan een ring omdat je meer figuren kan maken.  Een klok weergeven in een ster is misschien ook mogelijk, maar je moet er dan wel wat fantasie bij gebruiken.

HI8 videobanden converteren naar digitale video met hoge kwaliteit via Thunderbolt 3 (of 4) USB-C

Mijn verzameling oude HI8 banden widel ik graag omzetten naar digitale media, liefst met hoge kwaliteit.

Daarvoor heb ik verschillende methoden geprobeerd, waaronder de ouderwetse analoge opnamemachines zoals de Philips die een HDD gebruikten voor analoge TV-opname. Deze machines zijn ook uitgerust met een DVD opname mogelijkheid maar dit gaf nooit echt bevredigende resultaten, wat betreft de videokwaliteit.

Standalone analoge video converters naar USB gaven me ook nooit goede resultaten.

Na veel onderzoek ontdekte ik een manier om digitale video te genereren van een specifiek type Hi8 camera met DV output, en deze met een specifieke set apple converters om te zetten naar Thunderbolt 2 of -3 (USB-C).

Je hebt hiervoor wel een laptop of Mac of Ipad nodig met een Thunderbolt 3 of 4 aansluiting en de benodigde hardware voor Thunderbolt onder de motorkap.

Je kan ook een PC nemen en daar een firewire-800 kaart in monteren, dan heb je geen Apple converters nodig naar Thunderbolt.

De opstelling voor aansluiting op een Thunderbolt 3 USB-C poort van een laptop,  Mac of iPad ziet er als volgt uit:

De gebruikte componenten zijn:

1) Sony DCR 1 HV 330 Hi8 camcorder met mini DV firewire 400 in/uitgang:

2) Firewire 400/800 kabel van mini 6-pins naar Firewire ‘standaard’ 9-pins

Deze gaat in de camera, Firewire 400 4-pins
Deze Firewire 800 female plug gaat in de omzetter van Firewire 800 naar Thunderbolt 2

3) Firewire 800 (9-pins) naar Thunderbolt 2 (Apple) mini DV converter

Ingang met Firewire 800 9-polige aansluiting (5 onder en 4 bovenin, let op de locatorpin in het midden aan de bovenkant.  Daar past de Firewire 800 plug precies met de uitsparing in)

Uitgang met Thunderbolt 2 miniDV aansluiting

 

4) Converter Thunderbolt 2 naar Thunderbolt 3 (=USB-C) (Apple) nr. A1790

Ingang voor mini DV aansluiting Thunderbolt 2
En de uitgang naar Thunderbolt3 USB-C aansl;uiting die in de laptop of Mac kan met Thunderbolt 3 of 4 hardware

In apparaatbeheer staan na het aansluiten van de interfaces en de DV camcoder de volgende 2 nieuwe apparaten: (geel gemarkeerd)

En in de Thunderbolt Windows 11 app kun je de status van je Thunderbolt interface opvragen, waarin je dan de aangesloten Apple FireWire adapter actief ziet:

 

ANDERE OPLOSSING  1) met een Windows PC

Als je een PC hebt kun je een goedkope PC-PIE kaart kopen met firewire 800 (9-pins), dan heb je alleen de boven getoonde Firewire 400-800 kabel nodig om de DV camera aan te sluiten op de Firewire kaart van de PC.

Firewire PCIE card voor in een PC met 2x Firewire 800 9-polig en 1x Firewire 400 6-polige aansluiting

 

Of gebruik een goedkope Firewire PCIE  card met Firewire 400, dan heb je wel een andere Firewire 400 kabel nodig van 4-polig mini naar 6-polig standaard maar dat werkt ook.  Deze card gebruik ik voor mijn digitale back van de Mamiya RZ67 bij het importeren van video en foto’s.

Firewire 400 PCIE card voor in een PC met 3 x Firewire 400 6-polige standaard aansluitingen
Firewire 400 van mini 4-polig naar standaard 6-polig om de Sony Hi8 recorder (met DV Firewire 400) direct aan te sluiten op de PC’s PCIE Firewire PCIE adaptercard

Voor de import van de videstream kun je onder andere VLC mediaplayer gebruiken, via de streaming optie.  Wel gelijk even de opslag in VLC instellen zodat de gestreamde video wordt bewaard!

ANDERE OPLOSSING  2) met een Ubuntu computer

Mijn oude Ubuntu Shuttle Zotac PC uit 2016 heb ik uitgebreid met een PCIE FireWire 400 insteek kaart.

Daarna heb ik er dvgrab op gezet, via de volgende link:  https://zoomadmin.com/HowToInstall/UbuntuPackage/dvrgrab

In Ubuntu moet je daarna in de terminal app van Ubuntu een eenvoudige uitvoeringsregel invoeren om dvgrab aan het werk te zetten: dvgrab foo-, maar je kan ook een andere naam voor je files nemen en dan ziet je startregel er bijvoorbeeld zo uit: dvgrab jantec- of dvgrab vakantie_in_nederland_deel –

De gebruiksaaanwijzing van dvgrab staat hier: https://manpages.ubuntu.com/manpages/trusty/man1/dvgrab.1.html

dvgrab maakt van je video stukjes van bijna 2GB, net zolang tot de hele (Hi)8 tape is gimporteerd naar je persoonlijke hoofdmap.  Het format is dan .dv en dit kun je met o.a. een programma als HandBrake converteren naar elk gewenst format waaronder mp4 of AVI.  Handbrake is beschikbaar voor zowel Ubuntu (Linux) als Windows (alle versies)

Ik ben helemaal om en ga alleen de Ubuntu machine nog gebruiken voor deze toepassing, wel zo handig om wanneer het een keer nodig is een dedicated station te hebben voor video- en foto imports.

Opmerking 1: Op de Ubuntu machine kun je VLC mediaplayer trouwens ook installeren maar het is mij niet gelukt om de de Hi8 DV recorder via FireWire te koppelen aan VLC. Dat komt omdat VLC met door het Systeem herkende apparaten werkt en Ubuntu- c.q. dvgrab werkt rechtstreeks met het hardware FireWire interface.  VLC kan dat jammer genoeg niet.   Windows 11 maakt wel een apparaat aan (Sony DV recorder) dat VLC vervolgens kan herkennen en kan gebruiken maar bij Ubuntu werkt dat niet zo.

Opmerking 2: Uiteindelijk kwam ik ubuntustudio tegen als subrelease van de reguliere Ubuntu releases.  Deze versie is helemaal toegespitst op audio- en video gebruik, met FireWire.  Na installeren hiervan heb je precies de juiste apps en drivers om Digitale video van je FireWire te importeren, verwerken en op te slaan.

Sec6!

C) Jantec.nl 30 juni 2023, bijgewerkt tot 12 juli 2023

24V DC- & 230 Volt AC mini-windgenerator installatie

Aangeschaft om mee te experimenteren: Een mini windgenerator met 24V, 3 fasen en 400 Watt maximale opbrengst.  Inclusief regelaar om op een 24V accu aan te sluiten.

Daarachter komt de 24V DC naar 230V AC  2000 Watt , met het lichtnet gesynchroniseerde inverter.

Daarmee kan ik in huis alles aansluiten, behalve de grootverbruikers.  Verlichting is natuurlijk geen probleem, en de laptop voeden ook niet.  Voor de rest moeten we alles nog proberen, dat hoort ook zo bij een experimentele opzet.

De miniturbine komt op de nok van het dak met een verticale steigerbuis , tussen de huizen in en maakt geen herrie.  Het ontwerp van de Savonius turbine windvanger is daar op afgestemd.

 

Als test worden ook de 5 oorspronkelijke ‘schelp’-achtige rotorbladen gemonteerd, waarvan zowel geluid- als energieproductie wordt gemeten.

De 3-fase mini generator wordt met de regelaar (rechtsonder) geremd wanneer er te veel stroom wordt opgewekt…. . De montageplaat (rechtsboven) past op een 28mm buis en wordt aan deze buis gelast.  Dat past vervolgens in een steviger standaard diameter masttype.
De montageplaat voor de verticale mini savonius windvanger
Diameter van de montageplaat is ca 15 centimeter

De buitenpijp wordt verticaal op het dak net boven mijn Velux dakraam geplaatst , zo hoog mogelijk tegen de nokbalk aan,.

VOORBEELD van een mastinstallatie OP het dak. Dit wordt ook mijn manier van opstellen. De beugel is besteld.
Overzicht van het schuine dak met zonnepanelen en dakramen. Het gele vlakje geeft aan waar de dakbeugel voor de windrotor komt.

https://www.durasat.de/out/media/14473_DUR-line-Herkules_Produktinfo(3).pdf

De geaarde 3-fasekabel gaat door de mast door het dak naar binnen en de aarding van de mast en de gehele installatie komt rechtstreeks aan de al aanwezige aardinstallatie van de zonnepanelen.

De regelaar en de gesloten accu komt in de afgesloten beluchte CV ruimte op zolder.  Daar wordt de nieuwe windinstallatie aangesloten op de bestaande huisinstallatie, met een fasegestuurde omschakelaar.

De zonnepanelen (met een output aan 230V AC) gaan de 24V accu ook laden wanneer de windinstallatie onvoldoende oplevert en vice versa.

mobiele diesel heater in koffer met 12V lithium accu en PSU

Al een tijdje ben ik bezig met het verzamelen van onderdelen voor een standalone Vevor diesel heater voor in de garage of onderweg.

Het past allemaal netjes in (en aan) de TOM CASE koffer, het kan ruim 10 uur zonder opladen werken en gebruikt gewone dieselolie.

Naast de primaire luchtverwarming heb ik als extra een warmtewisselaar opgenomen in de uitlaat, zie bijgaande foto’s van de eerste opzet van de bouw:

De warmtewisselaar levert als dat nodig is warm circulatiewater voor een externe radiatorunit met ventilator.  De 12 Volt pompunit zit in de koffer, en deze pompunit gaat automatisch draaien wanneer het water warm is.

Er komt natuurlijk nog het een en ander bij, zoals:

  • 12V power supply en l;ader voor de lithium-ion accu
  • aan- en afvoer van lucht van de verwarming
  • aan- en afvoer van water voor de extra verwarming (van de warmtewisselaar)
  • pomp voor het verwarmingscircuit van de warmtewisselaar
  • externe radiator (en fan)  in het warntewisselaar circuit
  • glasvezel bescherming tegen overtollige hitte van de uitlaat
  • LCD bediening op de zijkant van de case
  • volt- en ampere meter van de 12V schakeling
  • 230V inlet en aan-uit schakelaar
  • Heel veel demping en isolatie
  • Dieselpomp, -filter en -leidingen

De 10 liter dieseltank is al op het deksel van de behuizing gemonteerd, de brandstofleiding komt met een aansluiting bovenin de tank met een aanzuigleiding naar beneden, voorzien van een grof inlaatfilter in de tank.

Boven: Het met ASA geprinte verloopstuk voor de luchtuitlaat

de pomp onder ca 30 graden geplaatst
Bovenaanzicht met de losjes geplaatste belangrijkste onderdelen
RFechter zijkant met het LCD, netspanningsinlet inclusief schakelaar, luchtinlaat en gasuitlaat. DE perforatrie met de gaatjes zorgt voor de doorstroming van koele lucht langs de uitlaat en dergelijke
De aan- uit schakelaar van de heater (12V switch)
De tank (hier liggend, maar normaal staat de koffer natuurlijk rechtop)
IN heb gekozen om het aanzuigpunt bovenin te maken en met een koperen leiding naar onder de diesel aan te zuigen. Dit voorkomt mogelijke diesel lekkage wanneer e.e.a. niet in gebruik is
Hier kun je nog een keer de routering van de aanzuig- en afvoer van de heater zien met de warmtewisselaar in de uitlaat opgenomen.
Het aanzuigpijpje dat helemaal naar beneden loopt in de dieseltank
Topaanzicht (De heater koffer ligt hier natuurlijk maar bij normaal gebruik staat de koffer met handvat aan de bovenkant)

 

 

GRA-AFCH NixieClockShield_NCS318_V1_94_TZ.ino met Time zone en zomer/wintertijd add-on met voorbeeld

Ik heb de timzone.lib plus arduino-additionele code toegevoegd aan de open-source code zoals GRA-AFCH die heeft gemaakt voor hun IN-18 nixie klok met Arduino Mega : NixieClockShield_NCS318_V1_94_TZ.

Hiermee synchroniseert de NIXIE klok via een aan te sluiten standaard GPS module met UTC (stond al in de code) en vervolgens met de juiste tijdzone, inclusief automatische verschuiving voor zomer- en wintertijd! (wat geheel nieuw is!)

Zie de werkende versie onder:

Het is nu gecodeerd voor West-Europa en een voorbeeld staat in de code voor een US tijdzone, andere kunnen worden afgeleid uit de voorbeelden die bij de nieuw toegevoegde timezone.lib zitten! #include <Timezone.h>//https://github.com/JChristensen/Timezone

Beschikbare tijdzones:

// Australia Eastern Time Zone (Sydney, Melbourne)
TimeChangeRule aEDT = {“AEDT”, First, Sun, Oct, 2, 660}; // UTC + 11 hours
TimeChangeRule aEST = {“AEST”, First, Sun, Apr, 3, 600}; // UTC + 10 hours
Timezone ausET(aEDT, aEST);

// Moscow Standard Time (MSK, does not observe DST)
TimeChangeRule msk = {“MSK”, Last, Sun, Mar, 1, 180};
Timezone tzMSK(msk);

// Central European Time (Frankfurt, Paris)
TimeChangeRule CEST = {“CEST”, Last, Sun, Mar, 2, 120}; // Central European Summer Time
TimeChangeRule CET = {“CET “, Last, Sun, Oct, 3, 60}; // Central European Standard Time
Timezone CE(CEST, CET);

// United Kingdom (London, Belfast)
TimeChangeRule BST = {“BST”, Last, Sun, Mar, 1, 60}; // British Summer Time
TimeChangeRule GMT = {“GMT”, Last, Sun, Oct, 2, 0}; // Standard Time
Timezone UK(BST, GMT);

// UTC
TimeChangeRule utcRule = {“UTC”, Last, Sun, Mar, 1, 0}; // UTC
Timezone UTC(utcRule);

// US Eastern Time Zone (New York, Detroit)
TimeChangeRule usEDT = {“EDT”, Second, Sun, Mar, 2, -240}; // Eastern Daylight Time = UTC – 4 hours
TimeChangeRule usEST = {“EST”, First, Sun, Nov, 2, -300}; // Eastern Standard Time = UTC – 5 hours
Timezone usET(usEDT, usEST);

// US Central Time Zone (Chicago, Houston)
TimeChangeRule usCDT = {“CDT”, Second, Sun, Mar, 2, -300};
TimeChangeRule usCST = {“CST”, First, Sun, Nov, 2, -360};
Timezone usCT(usCDT, usCST);

// US Mountain Time Zone (Denver, Salt Lake City)
TimeChangeRule usMDT = {“MDT”, Second, Sun, Mar, 2, -360};
TimeChangeRule usMST = {“MST”, First, Sun, Nov, 2, -420};
Timezone usMT(usMDT, usMST);

// Arizona is US Mountain Time Zone but does not use DST
Timezone usAZ(usMST);

// US Pacific Time Zone (Las Vegas, Los Angeles)
TimeChangeRule usPDT = {“PDT”, Second, Sun, Mar, 2, -420};
TimeChangeRule usPST = {“PST”, First, Sun, Nov, 2, -480};
Timezone usPT(usPDT, usPST);

De benodigde arduino libraries staan op de GRA-AFCH Github pagina’s hier:

https://github.com/afch/NixieClock

of download alleen de Libraries

Het werkt echt goed, zie het gezipte bestand hieronder of de arduino code verderop:

NixieClockShield_NCS318_V1_94_TZ.ino

NixieClockShield_NCS318_V1_94_TZ.ino:

const String FirmwareVersion = “0196TZ”;
const char HardwareVersion[] PROGMEM = {“NCS318/568 FW 1.94TZ 2021_04_04 Jantec.nl add-on for Timezones for HW 1.x HV5122 or HV5222”};

//// This ‘TZ’ firmware addition delivers automated Summer/Winter time changes based on your local time zone settings ////
//// Jantec.nl 2023-04-04 The Netherlands, Amsterdam. Please share and re-use! ////
//// This can and may be used in any CLOCK program, with possibly specific minor alteration, due to different libraries and do on ////
//// All of my add-ons are specified in the code! Cheers, Jantec.nl, NL ////
//// The approach here is to automatically change the EEPROM hours setting according to the SUMMER/WINTER timescheme ////
//// meaning: Put in the register: a) the time zone (=normal winter time) versus UTC and b) at the switching times the summer ‘+1’ change versus ‘normal’wintertime ///
//// If the user changes the hours setting, this will be overruled at every programmed time change related to summer/ winter time
//Format _X.XXX_
//NIXIE CLOCK SHIELD NCS318/568 for HW 1.x by GRA & AFCH (fominalec@gmail.com)
//1.94 26.02.2021
//Added: Сhecking the presence of a gps receiver when turned on.
//Return to the previous gps parser
//1.92 21.01.2021
//Added: defines for GPS receiver types
//1.91 29.07.2020
//The driver has been changed to support BOTH HV5122 and HV5222 registers (switching using resistor R5222 Arduino pin No. 8)
//1.90 08.06.2020
//Fixed: GPS timezone issue: added breakTime(now(), tm) to adjustTime function at Time.cpp
//1.89 03.04.2020
//Dots sync with seconds
//1.88 26.03.2020
//GPS synchronization algorithm has been changed (again)
//1.86 23.02.2020
//GPS synchronization algorithm changed
//1.85.3 23.02.2020
//Added: DS3231 internal temperature sensor self test: 5 beeps if fail.
//1.85.2 21.02.2020
//Fixed: Bug with time zones more than +-9
// GPS parser has been replaced by NEOGPS
//1.85.1 05.01.2020
//Value of “HardwareVersion” was changed to NCS318/568
//1.85 14.06.2019
//indication is working inside interrupt (only for Arduino Mega), driver v1.3 is required
//Added: support programmable leds ws2812b
//Some performance optimizations
//1.84 08.04.2018
//LEDs functions moved to external file
//LEDs freezing while music (or sound) played.
//SPI Setup moved driver’s file
//1.83 02.08.2018 (Driver v 1.1 is required)
//Fixed: Temp. reading speed fixed
//Fixed: Dots mixed up (driver was updated to v. 1.1)
//Fixed: RGB LEDs reading from EEPROM
//Fixed: Check for entering data from GPS in range
//1.82 18.07.2018 Dual Date Format
//1.81 18.02.2018 Temp. sensor present analyze
//1.80 06.08.2017
//Added: Date and Time GPS synchronization
//1.70 30.07.2017
//Added IR remote control support (Sony RM-X151) (“MODE”, “UP”, “DOWN”)
//1.60 24_07_2017
//Added: Temperature reading mode in menu and slot machine transaction
//1.0.31 27_04_2017
//Added: antipoisoning effect – slot machine
//1.021 31.01.2017
//Added: time synchronizing each 10 seconds
//Fixed: not correct time reading from RTC while start up
//1.02 17.10.2016
//Fixed: RGB color controls
//Update to Arduino IDE 1.6.12 (Time.h replaced to TimeLib.h)
//1.01
//Added RGB LEDs lock(by UP and Down Buttons)
//Added Down and Up buttons pause and resume self testing
//25.09.2016 update to HW ver 1.1
//25.05.2016

//#define tubes8
#define tubes6
//#define tubes4

#include <SPI.h>
#include <Wire.h>
#include <ClickButton.h>
#include <TimeLib.h>
#ifndef GRA_AND_AFCH_TIME_LIB_MOD
#error The “Time (TimeLib)” library modified by GRA and AFCH must be used!
#endif

//// THIS IS NEW, related to TIMEZONE add-on:
#include <Timezone.h>//https://github.com/JChristensen/Timezone
//Central European Time (Frankfurt, Paris)
TimeChangeRule myDST = {“CEST”, Last, Sun, Mar, 26, 120}; //Central European Summer Time//Daylight time = UTC +2 hours
TimeChangeRule mySTD = {“CET “, Last, Sun, Oct, 3, 60}; //Central European Standard Time (Winter)//Daylight time = UTC +1 hour
Timezone myTZ(myDST, mySTD);
//ADD AND REPLACE THE ABOVE FOR ANY OTHER REQUIRED TIMEZONE FROM THE EXAMPLES IN JChistensen’s exaples folders
// US Eastern Time Zone (New York, Detroit)
//TimeChangeRule myDST = {“EDT”, Second, Sun, Mar, 2, -240}; //Daylight time = UTC – 4 hours
//TimeChangeRule mySTD = {“EST”, First, Sun, Nov, 2, -300}; //Daylight time = UTC – 4 hours
//Timezone myTZ(myDST, mySTD);
TimeChangeRule *tcr; //pointer to the time change rule, use to get the TZ abbrev
time_t utc;
//// end of this add-on for TIMEZONE

#include <Tone.h>
#include <EEPROM.h>
#include “doIndication318_HW1.x.h”
#include <OneWire.h>
//IR remote control /////////// START /////////////////////////////
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)

#define GPS_SYNC_INTERVAL 1800000 // in milliseconds
//#define GPS_SYNC_INTERVAL 180000 //3 minutes
unsigned long Last_Time_GPS_Sync = 0;
//bool GPS_Sync_Flag = false;
//uint32_t GPS_Sync_Interval=120000; // 2 minutes
uint32_t GPS_Sync_Interval = 60000; // first try = 1 minute
uint32_t MillsNow=0;
#define TIME_TO_TRY 60000 //1 minute
bool AttMsgWasShowed=false;

#define GPS_BUFFER_LENGTH 83

char GPS_Package[GPS_BUFFER_LENGTH];
byte GPS_position = 0;

struct GPS_DATE_TIME
{
byte GPS_hours;
byte GPS_minutes;
byte GPS_seconds;
byte GPS_day;
byte GPS_mounth;
int GPS_year;
bool GPS_Valid_Data = false;
unsigned long GPS_Data_Parsed_time;
};

GPS_DATE_TIME GPS_Date_Time;

#define PreZero(digit) ((abs(digit)<10)?”0″+String(abs(digit)):String(abs(digit)))
#include <IRremote.h>
int RECV_PIN = 4;
IRrecv irrecv(RECV_PIN);
decode_results IRresults;
// buttons codes for remote controller Sony RM-X151
#define IR_BUTTON_UP_CODE 0x6621
#define IR_BUTTON_DOWN_CODE 0x2621
#define IR_BUTTON_MODE_CODE 0x7121

class IRButtonState
{
public:
int PAUSE_BETWEEN_PACKETS = 50;
int PACKETS_QTY_IN_LONG_PRESS = 18;

private:
bool Flag = 0;
byte CNT_packets = 0;
unsigned long lastPacketTime = 0;
bool START_TIMER = false;
int _buttonCode;

public: IRButtonState::IRButtonState(int buttonCode)
{
_buttonCode = buttonCode;
}

public: int IRButtonState::checkButtonState(int receivedCode)
{
if (((millis() – lastPacketTime) > PAUSE_BETWEEN_PACKETS) && (START_TIMER == true))
{
START_TIMER = false;
if (CNT_packets >= 2) {
Flag = 0;
CNT_packets = 0;
START_TIMER = false;
return 1;
}
else {
Flag = 0;
CNT_packets = 0;
return 0;
}
}
else
{
if (receivedCode == _buttonCode) { Flag = 1;}
else
{
if (!(Flag == 1)) {return 0;}
else
{
if (!(receivedCode == 0xFFFFFFFF)) {return 0;}
}
}
CNT_packets++;
lastPacketTime = millis();
START_TIMER = true;
if (CNT_packets >= PACKETS_QTY_IN_LONG_PRESS) {
Flag = 0;
CNT_packets = 0;
START_TIMER = false;
return -1;
}
else {return 0;}
}
}
};

IRButtonState IRModeButton(IR_BUTTON_MODE_CODE);
IRButtonState IRUpButton(IR_BUTTON_UP_CODE);
IRButtonState IRDownButton(IR_BUTTON_DOWN_CODE);
#endif

int ModeButtonState = 0;
int UpButtonState = 0;
int DownButtonState = 0;

//IR remote control /////////// START /////////////////////////////

/*#define GPS_BUFFER_LENGTH 83

char GPS_Package[GPS_BUFFER_LENGTH];
byte GPS_position=0;

struct GPS_DATE_TIME
{
byte GPS_hours;
byte GPS_minutes;
byte GPS_seconds;
byte GPS_day;
byte GPS_mounth;
int GPS_year;
bool GPS_Valid_Data=false;
unsigned long GPS_Data_Parsed_time;
};
*/
//GPS_DATE_TIME GPS_Date_Time;

unsigned long GPS_Data_Parsed_time;

boolean UD, LD; // DOTS control;

byte data[12];
byte addr[8];
int celsius, fahrenheit;

#define RedLedPin 9 //MCU WDM output for red LEDs 9-g
#define GreenLedPin 6 //MCU WDM output for green LEDs 6-b
#define BlueLedPin 3 //MCU WDM output for blue LEDs 3-r
#define pinSet A0
#define pinUp A2
#define pinDown A1
//#define pinBuzzer 2
const byte pinBuzzer = 2; // pomenyal
#define pinUpperDots 12 //HIGH value light a dots
#define pinLowerDots 8 //HIGH value light a dots
#define pinTemp 7
bool RTC_present;
#define US_DateFormat 1
#define EU_DateFormat 0
//bool DateFormat=EU_DateFormat;

OneWire ds(pinTemp);
bool TempPresent = false;
#define CELSIUS 0
#define FAHRENHEIT 1

String stringToDisplay = “000000”; // Content of this string will be displayed on tubes (must be 6 chars length)
int menuPosition = 0;
// 0 – time
// 1 – date
// 2 – alarm
// 3 – 12/24 hours mode
// 4 – Temperature
// 5 – TimeZone* (Only for Ardiono Mega)

byte blinkMask = B00000000; //bit mask for blinkin digits (1 – blink, 0 – constant light)
int blankMask = B00000000; //bit mask for digits (1 – off, 0 – on)

byte dotPattern = B00000000; //bit mask for separeting dots (1 – on, 0 – off)
//B10000000 – upper dots
//B01000000 – lower dots

#define DS1307_ADDRESS 0x68
byte zero = 0x00; //workaround for issue #527
int RTC_hours, RTC_minutes, RTC_seconds, RTC_day, RTC_month, RTC_year, RTC_day_of_week;

#define TimeIndex 0
#define DateIndex 1
#define AlarmIndex 2
#define hModeIndex 3
#define TemperatureIndex 4
#define TimeZoneIndex 5
#define TimeHoursIndex 6
#define TimeMintuesIndex 7
#define TimeSecondsIndex 8
#define DateFormatIndex 9
#define DateDayIndex 10
#define DateMonthIndex 11
#define DateYearIndex 12
#define AlarmHourIndex 13
#define AlarmMinuteIndex 14
#define AlarmSecondIndex 15
#define Alarm01 16
#define hModeValueIndex 17
#define DegreesFormatIndex 18
#define HoursOffsetIndex 19

#define FirstParent TimeIndex
#define LastParent TimeZoneIndex
#define SettingsCount (HoursOffsetIndex+1)
#define NoParent 0
#define NoChild 0

//——————————-0——–1——–2——-3——–4——–5——–6——–7——–8——–9———-10——-11———12———13——-14——-15———16———17——–18———-19
// names: Time, Date, Alarm, 12/24, Temperature,TimeZone,hours, mintues, seconds, DateFormat, day, month, year, hour, minute, second alarm01 hour_format Deg.FormIndex HoursOffset
// 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
int parent[SettingsCount] = {NoParent, NoParent, NoParent, NoParent,NoParent,NoParent,1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 5, 6};
int firstChild[SettingsCount] = {6, 9, 13, 17, 18, 19, 0, 0, 0, NoChild, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int lastChild[SettingsCount] = { 8, 12, 16, 17, 18, 19, 0, 0, 0, NoChild, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int value[SettingsCount] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, EU_DateFormat, 0, 0, 0, 0, 0, 0, 0, 24, 0, 2};
int maxValue[SettingsCount] = { 0, 0, 0, 0, 0, 0, 23, 59, 59, US_DateFormat, 31, 12, 99, 23, 59, 59, 1, 24, FAHRENHEIT, 14};
int minValue[SettingsCount] = { 0, 0, 0, 12, 0, 0, 00, 00, 00, EU_DateFormat, 1, 1, 00, 00, 00, 00, 0, 12, CELSIUS, -12};
int blinkPattern[SettingsCount] = {
B00000000, //0
B00000000, //1
B00000000, //2
B00000000, //3
B00000000, //4
B00000000, //5
B00000011, //6
B00001100, //7
B00110000, //8
B00111111, //9
B00000011, //10
B00001100, //11
B00110000, //12
B00000011, //13
B00001100, //14
B00110000, //15
B11000000, //16
B00001100, //17
B00111111, //18
B00000011, //19
};

bool editMode = false;

long downTime = 0;
long upTime = 0;
const long settingDelay = 150;
bool BlinkUp = false;
bool BlinkDown = false;
unsigned long enteringEditModeTime = 0;
bool RGBLedsOn = true;
#define RGBLEDsEEPROMAddress 0
#define HourFormatEEPROMAddress 1
#define AlarmTimeEEPROMAddress 2 //3,4,5
#define AlarmArmedEEPROMAddress 6
#define LEDsLockEEPROMAddress 7
#define LEDsRedValueEEPROMAddress 8
#define LEDsGreenValueEEPROMAddress 9
#define LEDsBlueValueEEPROMAddress 10
#define DegreesFormatEEPROMAddress 11
#define HoursOffsetEEPROMAddress 12
#define DateFormatEEPROMAddress 13

//buttons pins declarations
ClickButton setButton(pinSet, LOW, CLICKBTN_PULLUP);
ClickButton upButton(pinUp, LOW, CLICKBTN_PULLUP);
ClickButton downButton(pinDown, LOW, CLICKBTN_PULLUP);
///////////////////

Tone tone1;
#define isdigit(n) (n >= ‘0’ && n <= ‘9’)
//char *song = “MissionImp:d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d”;
char *song = “PinkPanther:d=4,o=5,b=160:8d#,8e,2p,8f#,8g,2p,8d#,8e,16p,8f#,8g,16p,8c6,8b,16p,8d#,8e,16p,8b,2a#,2p,16a,16g,16e,16d,2e”;
//char *song=”VanessaMae:d=4,o=6,b=70:32c7,32b,16c7,32g,32p,32g,32p,32d#,32p,32d#,32p,32c,32p,32c,32p,32c7,32b,16c7,32g#,32p,32g#,32p,32f,32p,16f,32c,32p,32c,32p,32c7,32b,16c7,32g,32p,32g,32p,32d#,32p,32d#,32p,32c,32p,32c,32p,32g,32f,32d#,32d,32c,32d,32d#,32c,32d#,32f,16g,8p,16d7,32c7,32d7,32a#,32d7,32a,32d7,32g,32d7,32d7,32p,32d7,32p,32d7,32p,16d7,32c7,32d7,32a#,32d7,32a,32d7,32g,32d7,32d7,32p,32d7,32p,32d7,32p,32g,32f,32d#,32d,32c,32d,32d#,32c,32d#,32f,16c”;
//char *song=”DasBoot:d=4,o=5,b=100:d#.4,8d4,8c4,8d4,8d#4,8g4,a#.4,8a4,8g4,8a4,8a#4,8d,2f.,p,f.4,8e4,8d4,8e4,8f4,8a4,c.,8b4,8a4,8b4,8c,8e,2g.,2p”;
//char *song=”Scatman:d=4,o=5,b=200:8b,16b,32p,8b,16b,32p,8b,2d6,16p,16c#.6,16p.,8d6,16p,16c#6,8b,16p,8f#,2p.,16c#6,8p,16d.6,16p.,16c#6,16b,8p,8f#,2p,32p,2d6,16p,16c#6,8p,16d.6,16p.,16c#6,16a.,16p.,8e,2p.,16c#6,8p,16d.6,16p.,16c#6,16b,8p,8b,16b,32p,8b,16b,32p,8b,2d6,16p,16c#.6,16p.,8d6,16p,16c#6,8b,16p,8f#,2p.,16c#6,8p,16d.6,16p.,16c#6,16b,8p,8f#,2p,32p,2d6,16p,16c#6,8p,16d.6,16p.,16c#6,16a.,16p.,8e,2p.,16c#6,8p,16d.6,16p.,16c#6,16a,8p,8e,2p,32p,16f#.6,16p.,16b.,16p.”;
//char *song=”Popcorn:d=4,o=5,b=160:8c6,8a#,8c6,8g,8d#,8g,c,8c6,8a#,8c6,8g,8d#,8g,c,8c6,8d6,8d#6,16c6,8d#6,16c6,8d#6,8d6,16a#,8d6,16a#,8d6,8c6,8a#,8g,8a#,c6″;
//char *song=”WeWishYou:d=4,o=5,b=200:d,g,8g,8a,8g,8f#,e,e,e,a,8a,8b,8a,8g,f#,d,d,b,8b,8c6,8b,8a,g,e,d,e,a,f#,2g,d,g,8g,8a,8g,8f#,e,e,e,a,8a,8b,8a,8g,f#,d,d,b,8b,8c6,8b,8a,g,e,d,e,a,f#,1g,d,g,g,g,2f#,f#,g,f#,e,2d,a,b,8a,8a,8g,8g,d6,d,d,e,a,f#,2g”;
#define OCTAVE_OFFSET 0
char *p;

int notes[] = { 0,
NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4,
NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B5,
NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6,
NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7
};

int fireforks[] = {0, 0, 1, //1
-1, 0, 0, //2
0, 1, 0, //3
0, 0, -1, //4
1, 0, 0, //5
0, -1, 0
}; //array with RGB rules (0 – do nothing, -1 – decrese, +1 – increse

void setRTCDateTime(byte h, byte m, byte s, byte d, byte mon, byte y, byte w = 1);

int functionDownButton = 0;
int functionUpButton = 0;
bool LEDsLock = false;

//antipoisoning transaction
bool modeChangedByUser = false;
bool transactionInProgress = false; //antipoisoning transaction
#define timeModePeriod 60000
#define dateModePeriod 5000
long modesChangePeriod = timeModePeriod;
//end of antipoisoning transaction

bool GPS_sync_flag=false;

extern const int LEDsDelay;

/*******************************************************************************************************
Init Programm
*******************************************************************************************************/
void setup()
{
Wire.begin();
//setRTCDateTime(23,40,00,25,7,15,1);

Serial.begin(115200);
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
Serial1.begin(9600);
digitalWrite(19, HIGH);
#endif

 

 

if (EEPROM.read(HourFormatEEPROMAddress) != 12) value[hModeValueIndex] = 24; else value[hModeValueIndex] = 12;
if (EEPROM.read(RGBLEDsEEPROMAddress) != 0) RGBLedsOn = true; else RGBLedsOn = false;
if (EEPROM.read(AlarmTimeEEPROMAddress) == 255) value[AlarmHourIndex] = 0; else value[AlarmHourIndex] = EEPROM.read(AlarmTimeEEPROMAddress);
if (EEPROM.read(AlarmTimeEEPROMAddress + 1) == 255) value[AlarmMinuteIndex] = 0; else value[AlarmMinuteIndex] = EEPROM.read(AlarmTimeEEPROMAddress + 1);
if (EEPROM.read(AlarmTimeEEPROMAddress + 2) == 255) value[AlarmSecondIndex] = 0; else value[AlarmSecondIndex] = EEPROM.read(AlarmTimeEEPROMAddress + 2);
if (EEPROM.read(AlarmArmedEEPROMAddress) == 255) value[Alarm01] = 0; else value[Alarm01] = EEPROM.read(AlarmArmedEEPROMAddress);
if (EEPROM.read(LEDsLockEEPROMAddress) == 255) LEDsLock = false; else LEDsLock = EEPROM.read(LEDsLockEEPROMAddress);
if (EEPROM.read(DegreesFormatEEPROMAddress) == 255) value[DegreesFormatIndex] = CELSIUS; else value[DegreesFormatIndex] = EEPROM.read(DegreesFormatEEPROMAddress);
if (EEPROM.read(HoursOffsetEEPROMAddress) == 255) value[HoursOffsetIndex] = value[HoursOffsetIndex]; else value[HoursOffsetIndex] = EEPROM.read(HoursOffsetEEPROMAddress) + minValue[HoursOffsetIndex];

//// needed to set this HoursOffsetIndex variable to 0 since we will use the timezone lib (local timezone and summer/winter time add-ons by Jantec.nl)
value[HoursOffsetIndex] = 0;
EEPROM.write(HoursOffsetEEPROMAddress, 0);

if (EEPROM.read(DateFormatEEPROMAddress) == 255) value[DateFormatIndex] = value[DateFormatIndex]; else value[DateFormatIndex] = EEPROM.read(DateFormatEEPROMAddress);

//Serial.print(F(“led lock=”));
//Serial.println(LEDsLock);

pinMode(RedLedPin, OUTPUT);
pinMode(GreenLedPin, OUTPUT);
pinMode(BlueLedPin, OUTPUT);

tone1.begin(pinBuzzer);
song = parseSong(song);

pinMode(LEpin, OUTPUT);

// SPI setup
SPISetup();
LEDsSetup();
//buttons pins inits
pinMode(pinSet, INPUT_PULLUP);
pinMode(pinUp, INPUT_PULLUP);
pinMode(pinDown, INPUT_PULLUP);
////////////////////////////
pinMode(pinBuzzer, OUTPUT);

//buttons objects inits
setButton.debounceTime = 20; // Debounce timer in ms
setButton.multiclickTime = 30; // Time limit for multi clicks
setButton.longClickTime = 2000; // time until “held-down clicks” register

upButton.debounceTime = 20; // Debounce timer in ms
upButton.multiclickTime = 30; // Time limit for multi clicks
upButton.longClickTime = 2000; // time until “held-down clicks” register

downButton.debounceTime = 20; // Debounce timer in ms
downButton.multiclickTime = 30; // Time limit for multi clicks
downButton.longClickTime = 2000; // time until “held-down clicks” register

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
timerSetup();
#endif
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
doTest();
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (LEDsLock == 1)
{
setLEDsFromEEPROM();
}
getRTCTime();
byte prevSeconds = RTC_seconds;
unsigned long RTC_ReadingStartTime = millis();
RTC_present = true;
while (prevSeconds == RTC_seconds)
{
getRTCTime();
//Serial.println(RTC_seconds);
if ((millis() – RTC_ReadingStartTime) > 3000)
{
#ifdef DEBUG
Serial.println(F(“Warning! RTC DON’T RESPOND!”));
#endif
RTC_present = false;
break;
}
}
setTime(RTC_hours, RTC_minutes, RTC_seconds, RTC_day, RTC_month, RTC_year);

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
irrecv.blink13(false);
irrecv.enableIRIn(); // Start the receiver
#endif

//// add-ons for TIMEZONE
time_t utc = now();
time_t local = myTZ.toLocal(utc, &tcr);
Serial.println();
printDateTime(utc, “UTC”);
printDateTime(local, tcr -> abbrev);
delay(1000);//was 10000
//// end of add-ons for TIMEZONE

}

int rotator = 0; //index in array with RGB “rules” (increse by one on each 255 cycles)
int cycle = 0; //cycles counter
int RedLight = 255;
int GreenLight = 0;
int BlueLight = 0;
unsigned long prevTime = 0; // time of lase tube was lit
unsigned long prevTime4FireWorks = 0; //time of last RGB changed
//int minuteL=0; //младшая цифра минут

/***************************************************************************************************************
MAIN Programm
***************************************************************************************************************/
void loop() {

if (((millis() % 10000) == 0) && (RTC_present)) //synchronize with RTC every 10 seconds
{
getRTCTime();

setTime(RTC_hours, RTC_minutes, RTC_seconds, RTC_day, RTC_month, RTC_year);
// 4 lines of time zone & winter/summer time additions by Jantec.nl 2023 0404
time_t utc = now();
time_t local = myTZ.toLocal(utc, &tcr);
setTime(myTZ.toLocal(utc, &tcr));
EEPROM.write(DateFormatEEPROMAddress, value[myTZ.toLocal(utc, &tcr)]);

//Serial.println(F(“Sync”));
}

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)

MillsNow=millis();
if ((MillsNow – Last_Time_GPS_Sync) > GPS_Sync_Interval)
{
//GPS_Sync_Interval = GPS_SYNC_INTERVAL; // <—-!
//GPS_Sync_Flag = 0;
if (AttMsgWasShowed==false)
{
Serial.println(F(“Attempt to sync with GPS.”));
AttMsgWasShowed=true;
}
GetDataFromSerial1();
//SyncWithGPS();
}
if ((MillsNow – Last_Time_GPS_Sync) > GPS_Sync_Interval + TIME_TO_TRY)
{
Last_Time_GPS_Sync=MillsNow; //if it is not possible to synchronize within the allotted time TIME_TO_TRY, then we postpone attempts to the next time interval.
//GPS_Sync_Flag = 1;
//GPS_Sync_Interval = GPS_SYNC_INTERVAL;
Serial.println(F(“All attempts were unsuccessful.”));
AttMsgWasShowed=false;
}

IRresults.value = 0;
if (irrecv.decode(&IRresults)) {
Serial.println(IRresults.value, HEX);
irrecv.resume(); // Receive the next value
}

ModeButtonState = IRModeButton.checkButtonState(IRresults.value);
if (ModeButtonState == 1) Serial.println(F(“Mode short”));
if (ModeButtonState == -1) Serial.println(F(“Mode long….”));

UpButtonState = IRUpButton.checkButtonState(IRresults.value);
if (UpButtonState == 1) Serial.println(F(“Up short”));
if (UpButtonState == -1) Serial.println(F(“Up long….”));

DownButtonState = IRDownButton.checkButtonState(IRresults.value);
if (DownButtonState == 1) Serial.println(F(“Down short”));
if (DownButtonState == -1) Serial.println(F(“Down long….”));

#else
ModeButtonState=0;
UpButtonState=0;
DownButtonState=0;
#endif

p = playmusic(p);

if ((millis() – prevTime4FireWorks) > LEDsDelay)
{
rotateFireWorks(); //change color (by 1 step)
prevTime4FireWorks = millis();
}

if ((menuPosition == TimeIndex) || (modeChangedByUser == false) ) modesChanger();
#if defined (__AVR_ATmega328P__)
doIndication();
#endif

setButton.Update();
upButton.Update();
downButton.Update();
if (editMode == false)
{
blinkMask = B00000000;

} else if ((millis() – enteringEditModeTime) > 60000)
{
editMode = false;
menuPosition = firstChild[menuPosition];
blinkMask = blinkPattern[menuPosition];
}
if ((setButton.clicks > 0) || (ModeButtonState == 1)) //short click
{
modeChangedByUser = true;
p = 0; //shut off music )))
tone1.play(1000, 100);
enteringEditModeTime = millis();
/*if (value[DateFormatIndex] == US_DateFormat)
{
//if (menuPosition == )
} else */
menuPosition = menuPosition + 1;
#if defined (__AVR_ATmega328P__)
if (menuPosition == TimeZoneIndex) menuPosition++;// skip TimeZone for Arduino Uno
#endif
if (menuPosition == LastParent + 1) menuPosition = TimeIndex;
/*Serial.print(F(“menuPosition=”));
Serial.println(menuPosition);
Serial.print(F(“value=”));
Serial.println(value[menuPosition]);*/

blinkMask = blinkPattern[menuPosition];
if ((parent[menuPosition – 1] != 0) and (lastChild[parent[menuPosition – 1] – 1] == (menuPosition – 1))) //exit from edit mode
{
if ((parent[menuPosition – 1] – 1 == 1) && (!isValidDate()))
{
menuPosition = DateDayIndex;
return;
}
editMode = false;
menuPosition = parent[menuPosition – 1] – 1;
if (menuPosition == TimeIndex) setTime(value[TimeHoursIndex], value[TimeMintuesIndex], value[TimeSecondsIndex], day(), month(), year());
if (menuPosition == DateIndex)
{
#ifdef DEBUG
Serial.print(F(“Day:”));
Serial.println(value[DateDayIndex]);
Serial.print(F(“Month:”));
Serial.println(value[DateMonthIndex]);
#endif
setTime(hour(), minute(), second(), value[DateDayIndex], value[DateMonthIndex], 2000 + value[DateYearIndex]);
EEPROM.write(DateFormatEEPROMAddress, value[DateFormatIndex]);
}
if (menuPosition == AlarmIndex) {
EEPROM.write(AlarmTimeEEPROMAddress, value[AlarmHourIndex]);
EEPROM.write(AlarmTimeEEPROMAddress + 1, value[AlarmMinuteIndex]);
EEPROM.write(AlarmTimeEEPROMAddress + 2, value[AlarmSecondIndex]);
EEPROM.write(AlarmArmedEEPROMAddress, value[Alarm01]);
};
if (menuPosition == hModeIndex) EEPROM.write(HourFormatEEPROMAddress, value[hModeValueIndex]);
if (menuPosition == TemperatureIndex)
{
EEPROM.write(DegreesFormatEEPROMAddress, value[DegreesFormatIndex]);
}
if (menuPosition == TimeZoneIndex) EEPROM.write(HoursOffsetEEPROMAddress, value[HoursOffsetIndex] – minValue[HoursOffsetIndex]);
//if (menuPosition == hModeIndex) EEPROM.write(HourFormatEEPROMAddress, value[hModeValueIndex]);
setRTCDateTime(hour(), minute(), second(), day(), month(), year() % 1000, 1);
return;
} //end exit from edit mode
/*Serial.print(“menu pos=”);
Serial.println(menuPosition);
Serial.print(“DateFormat”);
Serial.println(value[DateFormatIndex]);*/
if ((menuPosition != HoursOffsetIndex) &&
(menuPosition != DateFormatIndex) &&
(menuPosition != DateDayIndex)) value[menuPosition] = extractDigits(blinkMask);
}
if ((setButton.clicks < 0) || (ModeButtonState == -1)) //long click
{
tone1.play(1000, 100);
if (!editMode)
{
enteringEditModeTime = millis();
if (menuPosition == TimeIndex) stringToDisplay = PreZero(hour()) + PreZero(minute()) + PreZero(second()); //temporary enabled 24 hour format while settings
}
if (menuPosition == DateIndex)
{
// Serial.println(“DateEdit”);
value[DateDayIndex] = day();
value[DateMonthIndex] = month();
value[DateYearIndex] = year() % 1000;
if (value[DateFormatIndex] == EU_DateFormat) stringToDisplay=PreZero(value[DateDayIndex])+PreZero(value[DateMonthIndex])+PreZero(value[DateYearIndex]);
else stringToDisplay=PreZero(value[DateMonthIndex])+PreZero(value[DateDayIndex])+PreZero(value[DateYearIndex]);
//Serial.print(“str=”);
// Serial.println(stringToDisplay);
}
menuPosition = firstChild[menuPosition];
if (menuPosition == AlarmHourIndex) {
value[Alarm01] = 1; /*digitalWrite(pinUpperDots, HIGH);*/dotPattern = B10000000;
}
editMode = !editMode;
blinkMask = blinkPattern[menuPosition];
if ((menuPosition != DegreesFormatIndex) &&
(menuPosition != HoursOffsetIndex) &&
(menuPosition != DateFormatIndex))
value[menuPosition] = extractDigits(blinkMask);
/*Serial.print(F(“menuPosition=”));
Serial.println(menuPosition);
Serial.print(F(“value=”));
Serial.println(value[menuPosition]); */
}

if (upButton.clicks != 0) functionUpButton = upButton.clicks;

if ((upButton.clicks > 0) || (UpButtonState == 1))
{
modeChangedByUser = true;
p = 0; //shut off music )))
tone1.play(1000, 100);
incrementValue();
if (!editMode)
{
LEDsLock = false;
EEPROM.write(LEDsLockEEPROMAddress, 0);
}
}

if (functionUpButton == -1 && upButton.depressed == true)
{
BlinkUp = false;
if (editMode == true)
{
if ( (millis() – upTime) > settingDelay)
{
upTime = millis();// + settingDelay;
incrementValue();
}
}
} else BlinkUp = true;

if (downButton.clicks != 0) functionDownButton = downButton.clicks;

if ((downButton.clicks > 0) || (DownButtonState == 1))
{
modeChangedByUser = true;
p = 0; //shut off music )))
tone1.play(1000, 100);
dicrementValue();
if (!editMode)
{
LEDsLock = true;
EEPROM.write(LEDsLockEEPROMAddress, 1);
EEPROM.write(LEDsRedValueEEPROMAddress, RedLight);
EEPROM.write(LEDsGreenValueEEPROMAddress, GreenLight);
EEPROM.write(LEDsBlueValueEEPROMAddress, BlueLight);
/*Serial.println(F(“Store to EEPROM:”));
Serial.print(F(“RED=”));
Serial.println(RedLight);
Serial.print(F(“GREEN=”));
Serial.println(GreenLight);
Serial.print(F(“Blue=”));
Serial.println(BlueLight);*/
}
}

if (functionDownButton == -1 && downButton.depressed == true)
{
BlinkDown = false;
if (editMode == true)
{
if ( (millis() – downTime) > settingDelay)
{
downTime = millis();// + settingDelay;
dicrementValue();
}
}
} else BlinkDown = true;

if (!editMode)
{
if ((upButton.clicks < 0) || (UpButtonState == -1))
{
tone1.play(1000, 100);
RGBLedsOn = true;
EEPROM.write(RGBLEDsEEPROMAddress, 1);
#ifdef DEBUG
Serial.println(F(“RGB=on”));
#endif
setLEDsFromEEPROM();
}
if ((downButton.clicks < 0) || (DownButtonState == -1))
{
tone1.play(1000, 100);
RGBLedsOn = false;
EEPROM.write(RGBLEDsEEPROMAddress, 0);
#ifdef DEBUG
Serial.println(F(“RGB=off”));
#endif
}
}

static bool updateDateTime = false;
float curTemp=0;
switch (menuPosition)
{
case TimeIndex: //time mode
if (!transactionInProgress) stringToDisplay = updateDisplayString();
doDotBlink();
checkAlarmTime();
blankMask = B00000000;
break;
case DateIndex: //date mode
if (!transactionInProgress) stringToDisplay = updateDateString();
dotPattern = B01000000; //turn on lower dots
checkAlarmTime();
blankMask = B00000000;
break;
case AlarmIndex: //alarm mode
//stringToDisplay=”000000″;
//unsigned long execTime;
//execTime=micros();
stringToDisplay = PreZero(value[AlarmHourIndex]) + PreZero(value[AlarmMinuteIndex]) + PreZero(value[AlarmSecondIndex]);
blankMask = B00000000;
if (value[Alarm01] == 1) dotPattern = B10000000; //turn on upper dots
else
{
dotPattern = B00000000; //turn off upper dots
}
//execTime=micros()-execTime;
//Serial.println(execTime);
checkAlarmTime();
break;
case hModeIndex: //12/24 hours mode
stringToDisplay = “00” + String(value[hModeValueIndex]) + “00”;
blankMask = B00110011;
dotPattern = B00000000; //turn off all dots
checkAlarmTime();
break;
case TemperatureIndex: //missed break
case DegreesFormatIndex:

if (!transactionInProgress)
{
curTemp=getTemperature(value[DegreesFormatIndex]);
stringToDisplay = updateTemperatureString(curTemp);
if (value[DegreesFormatIndex] == CELSIUS)
{
blankMask = B00110001;
dotPattern = B01000000;
}
else
{
blankMask = B00100011;
dotPattern = B00000000;
}
}

if (curTemp < 0) dotPattern |= B10000000;
else dotPattern &= B01111111;
break;
case TimeZoneIndex:
case HoursOffsetIndex:
stringToDisplay = String(PreZero(value[HoursOffsetIndex])) + “0000”;
blankMask = B00001111;
if (value[HoursOffsetIndex]>=0) dotPattern = B00000000; //turn off all dots
else dotPattern = B10000000; //turn on upper dots
break;
case DateFormatIndex:
if (value[DateFormatIndex] == EU_DateFormat)
{
stringToDisplay=”311299″;
blinkPattern[DateDayIndex]=B00000011;
blinkPattern[DateMonthIndex]=B00001100;
}
else
{
stringToDisplay=”123199″;
blinkPattern[DateDayIndex]=B00001100;
blinkPattern[DateMonthIndex]=B00000011;
}
break;
case DateDayIndex:
case DateMonthIndex:
case DateYearIndex:
if (value[DateFormatIndex] == EU_DateFormat) stringToDisplay=PreZero(value[DateDayIndex])+PreZero(value[DateMonthIndex])+PreZero(value[DateYearIndex]);
else stringToDisplay=PreZero(value[DateMonthIndex])+PreZero(value[DateDayIndex])+PreZero(value[DateYearIndex]);
break;
}
// IRresults.value=0;
}
#if defined (__AVR_ATmega328P__)
String PreZero(int digit)
{
digit=abs(digit);
if (digit < 10) return String(“0”) + String(digit);
//if (digit < 10) return “0” + String(digit);
else return String(digit);
}
#endif

String updateDisplayString()
{
static int prevS=-1;

if (second()!=prevS)
{
prevS=second();
return getTimeNow();
} else return stringToDisplay;
}

String getTimeNow()
{
if (value[hModeValueIndex] == 24) return PreZero(hour()) + PreZero(minute()) + PreZero(second());
else return PreZero(hourFormat12()) + PreZero(minute()) + PreZero(second());
}
//// add-on void for TIMEZONE ////////////////////////////////////////////////////////////
// format and print a time_t value, with a time zone appended.
void printDateTime(time_t t, const char *tz)
{
char buf[32];
char m[4]; // temporary storage for month string (DateStrings.cpp uses shared buffer)
strcpy(m, monthShortStr(month(t)));
sprintf(buf, “%.2d:%.2d:%.2d %s %.2d %s %d %s”,
hour(t), minute(t), second(t), dayShortStr(weekday(t)), day(t), m, year(t), tz);
Serial.println(buf);
}
/////// Jantec.nl 2023-04-04 The Netherlands, Amsterdam. Please share and re-use! ////////
void doTest()
{
Serial.print(F(“Firmware version: “));
Serial.println(FirmwareVersion.substring(1,2)+”.”+FirmwareVersion.substring(2,5));
for (byte k = 0; k < strlen_P(HardwareVersion); k++) {
Serial.print((char)pgm_read_byte_near(HardwareVersion + k));
}
Serial.println();
#ifdef DEBUG
Serial.println(F(“Start Test”));
#endif

p=song;
parseSong(p);
//p=0; //need to be deleted

LEDsTest();
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
if (Serial1.available() > 20) Serial.println(F(“GPS detected”));
else Serial.println(F(“GPS NOT detected!”));
#endif

#ifdef tubes8
String testStringArray[11]={“00000000″,”11111111″,”22222222″,”33333333″,”44444444″,”55555555″,”66666666″,”77777777″,”88888888″,”99999999″,””};
testStringArray[10]=FirmwareVersion+”00″;
#endif
#ifdef tubes6
String testStringArray[11]={“000000″,”111111″,”222222″,”333333″,”444444″,”555555″,”666666″,”777777″,”888888″,”999999″,””};
testStringArray[10]=FirmwareVersion;
#endif

int dlay=500;
bool test=1;
byte strIndex=-1;
unsigned long startOfTest=millis()+1000; //disable delaying in first iteration
bool digitsLock=false;
while (test)
{
if (digitalRead(pinDown)==0) digitsLock=true;
if (digitalRead(pinUp)==0) digitsLock=false;

if ((millis()-startOfTest)>dlay)
{
startOfTest=millis();
if (!digitsLock) strIndex=strIndex+1;
if (strIndex==10) dlay=2000;
if (strIndex>10) { test=false; strIndex=10;}

stringToDisplay=testStringArray[strIndex];
#ifdef DEBUG
Serial.println(stringToDisplay);
#endif
}
#if defined (__AVR_ATmega328P__)
doIndication();
#endif
}

if ( !ds.search(addr))
{
#ifdef DEBUG
Serial.println(F(“Temp. sensor not found.”));
#endif
} else TempPresent=true;

testDS3231TempSensor();

#ifdef DEBUG
Serial.println(F(“Stop Test”));
#endif
// while(1);
}

void doDotBlink()
{
if (second()%2 == 0) dotPattern = B11000000;
else dotPattern = B00000000;
}

void setRTCDateTime(byte h, byte m, byte s, byte d, byte mon, byte y, byte w)
{
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(zero); //stop Oscillator

Wire.write(decToBcd(s));
Wire.write(decToBcd(m));
Wire.write(decToBcd(h));
Wire.write(decToBcd(w));
Wire.write(decToBcd(d));
Wire.write(decToBcd(mon));
Wire.write(decToBcd(y));

Wire.write(zero); //start

Wire.endTransmission();

}

byte decToBcd(byte val) {
// Convert normal decimal numbers to binary coded decimal
return ( (val / 10 * 16) + (val % 10) );
}

byte bcdToDec(byte val) {
// Convert binary coded decimal to normal decimal numbers
return ( (val / 16 * 10) + (val % 16) );
}

void getRTCTime()
{
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(zero);
Wire.endTransmission();

Wire.requestFrom(DS1307_ADDRESS, 7);

RTC_seconds = bcdToDec(Wire.read());
RTC_minutes = bcdToDec(Wire.read());
RTC_hours = bcdToDec(Wire.read() & 0b111111); //24 hour time
RTC_day_of_week = bcdToDec(Wire.read()); //0-6 -> sunday – Saturday
RTC_day = bcdToDec(Wire.read());
RTC_month = bcdToDec(Wire.read());
RTC_year = bcdToDec(Wire.read());
}

int extractDigits(byte b)
{
String tmp = “1”;

if (b == B00000011)
{
tmp = stringToDisplay.substring(0, 2);
}
if (b == B00001100)
{
tmp = stringToDisplay.substring(2, 4);
}
if (b == B00110000)
{
tmp = stringToDisplay.substring(4);
}
return tmp.toInt();
}

void injectDigits(byte b, int value)
{
if (b == B00000011) stringToDisplay = PreZero(value) + stringToDisplay.substring(2);
if (b == B00001100) stringToDisplay = stringToDisplay.substring(0, 2) + PreZero(value) + stringToDisplay.substring(4);
if (b == B00110000) stringToDisplay = stringToDisplay.substring(0, 4) + PreZero(value);
}

bool isValidDate()
{
int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (value[DateYearIndex] % 4 == 0) days[1] = 29;
if (value[DateDayIndex] > days[value[DateMonthIndex] – 1]) return false;
else return true;

}

byte default_dur = 4;
byte default_oct = 6;
int bpm = 63;
int num;
long wholenote;
long duration;
byte note;
byte scale;
char* parseSong(char *p)
{
// Absolutely no error checking in here
// format: d=N,o=N,b=NNN:
// find the start (skip name, etc)

while (*p != ‘:’) p++; // ignore name
p++; // skip ‘:’

// get default duration
if (*p == ‘d’)
{
p++; p++; // skip “d=”
num = 0;
while (isdigit(*p))
{
num = (num * 10) + (*p++ – ‘0’);
}
if (num > 0) default_dur = num;
p++; // skip comma
}

// get default octave
if (*p == ‘o’)
{
p++; p++; // skip “o=”
num = *p++ – ‘0’;
if (num >= 3 && num <= 7) default_oct = num;
p++; // skip comma
}

// get BPM
if (*p == ‘b’)
{
p++; p++; // skip “b=”
num = 0;
while (isdigit(*p))
{
num = (num * 10) + (*p++ – ‘0’);
}
bpm = num;
p++; // skip colon
}

// BPM usually expresses the number of quarter notes per minute
wholenote = (60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds)
return p;
}

// now begin note loop
static unsigned long lastTimeNotePlaying = 0;
char* playmusic(char *p)
{
if (*p == 0)
{
return p;
}
if (millis() – lastTimeNotePlaying > duration)
lastTimeNotePlaying = millis();
else return p;
// first, get note duration, if available
num = 0;
while (isdigit(*p))
{
num = (num * 10) + (*p++ – ‘0’);
}

if (num) duration = wholenote / num;
else duration = wholenote / default_dur; // we will need to check if we are a dotted note after

// now get the note
note = 0;

switch (*p)
{
case ‘c’:
note = 1;
break;
case ‘d’:
note = 3;
break;
case ‘e’:
note = 5;
break;
case ‘f’:
note = 6;
break;
case ‘g’:
note = 8;
break;
case ‘a’:
note = 10;
break;
case ‘b’:
note = 12;
break;
case ‘p’:
default:
note = 0;
}
p++;

// now, get optional ‘#’ sharp
if (*p == ‘#’)
{
note++;
p++;
}

// now, get optional ‘.’ dotted note
if (*p == ‘.’)
{
duration += duration / 2;
p++;
}

// now, get scale
if (isdigit(*p))
{
scale = *p – ‘0’;
p++;
}
else
{
scale = default_oct;
}

scale += OCTAVE_OFFSET;

if (*p == ‘,’)
p++; // skip comma for next note (or we may be at the end)

// now play the note

if (note)
{
tone1.play(notes[(scale – 4) * 12 + note], duration);
if (millis() – lastTimeNotePlaying > duration)
lastTimeNotePlaying = millis();
else return p;
tone1.stop();
}
else
{
return p;
}
#ifdef DEBUG
Serial.println(F(“Incorrect Song Format!”));
#endif
return 0; //error
}

void incrementValue()
{
enteringEditModeTime = millis();
if (editMode == true)
{
if (menuPosition != hModeValueIndex) // 12/24 hour mode menu position
value[menuPosition] = value[menuPosition] + 1; else value[menuPosition] = value[menuPosition] + 12;
if (value[menuPosition] > maxValue[menuPosition]) value[menuPosition] = minValue[menuPosition];
if (menuPosition == Alarm01)
{
if (value[menuPosition] == 1) /*digitalWrite(pinUpperDots, HIGH);*/dotPattern = B10000000; //turn on upper dots
/*else digitalWrite(pinUpperDots, LOW); */ dotPattern = B00000000; //turn off all dots
}
if (menuPosition!=DateFormatIndex) injectDigits(blinkMask, value[menuPosition]);
/*Serial.print(“value=”);
Serial.println(value[menuPosition]);*/
}
}

void dicrementValue()
{
enteringEditModeTime = millis();
if (editMode == true)
{
if (menuPosition != hModeValueIndex) value[menuPosition] = value[menuPosition] – 1; else value[menuPosition] = value[menuPosition] – 12;
if (value[menuPosition] < minValue[menuPosition]) value[menuPosition] = maxValue[menuPosition];
if (menuPosition == Alarm01)
{
if (value[menuPosition] == 1) /*digitalWrite(pinUpperDots, HIGH);*/ dotPattern = B10000000; //turn on upper dots
else /*digitalWrite(pinUpperDots, LOW);*/ dotPattern = B00000000; //turn off all dots
}
if (menuPosition!=DateFormatIndex) injectDigits(blinkMask, value[menuPosition]);
/*Serial.print(“value=”);
Serial.println(value[menuPosition]);*/
}
}

bool Alarm1SecondBlock = false;
unsigned long lastTimeAlarmTriggired = 0;
void checkAlarmTime()
{
if (value[Alarm01] == 0) return;
if ((Alarm1SecondBlock == true) && ((millis() – lastTimeAlarmTriggired) > 1000)) Alarm1SecondBlock = false;
if (Alarm1SecondBlock == true) return;
if ((hour() == value[AlarmHourIndex]) && (minute() == value[AlarmMinuteIndex]) && (second() == value[AlarmSecondIndex]))
{
lastTimeAlarmTriggired = millis();
Alarm1SecondBlock = true;
#ifdef DEBUG
Serial.println(F(“Wake up, Neo!”));
#endif
p = song;
}
}

void modesChanger()
{
if (editMode == true) return;
static unsigned long lastTimeModeChanged = millis();
static unsigned long lastTimeAntiPoisoningIterate = millis();
static int transnumber = 0;
if ((millis() – lastTimeModeChanged) > modesChangePeriod)
{
lastTimeModeChanged = millis();
if (transnumber == 0) {
menuPosition = DateIndex;
modesChangePeriod = dateModePeriod;
}
if (transnumber == 1) {
menuPosition = TemperatureIndex;
modesChangePeriod = dateModePeriod;
if (!TempPresent) transnumber = 2;
}
if (transnumber == 2) {
menuPosition = TimeIndex;
modesChangePeriod = timeModePeriod;
}
transnumber++;
if (transnumber > 2) transnumber = 0;

if (modeChangedByUser == true)
{
menuPosition = TimeIndex;
}
modeChangedByUser = false;
}
if ((millis() – lastTimeModeChanged) < 2000)
{
if ((millis() – lastTimeAntiPoisoningIterate) > 100)
{
lastTimeAntiPoisoningIterate = millis();
if (TempPresent)
{
if (menuPosition == TimeIndex) stringToDisplay = antiPoisoning2(updateTemperatureString(getTemperature(value[DegreesFormatIndex])), getTimeNow());
if (menuPosition == DateIndex) stringToDisplay = antiPoisoning2(getTimeNow(), PreZero(day()) + PreZero(month()) + PreZero(year() % 1000) );
if (menuPosition == TemperatureIndex) stringToDisplay = antiPoisoning2(PreZero(day()) + PreZero(month()) + PreZero(year() % 1000), updateTemperatureString(getTemperature(value[DegreesFormatIndex])));
} else
{
if (menuPosition == TimeIndex) stringToDisplay = antiPoisoning2(PreZero(day()) + PreZero(month()) + PreZero(year() % 1000), getTimeNow());
if (menuPosition == DateIndex) stringToDisplay = antiPoisoning2(getTimeNow(), PreZero(day()) + PreZero(month()) + PreZero(year() % 1000) );
}
// Serial.println(“StrTDInToModeChng=”+stringToDisplay);
}
} else
{
transactionInProgress = false;
}
}

String antiPoisoning2(String fromStr, String toStr)
{
//static bool transactionInProgress=false;
//byte fromDigits[6];
static byte toDigits[6];
static byte currentDigits[6];
static byte iterationCounter = 0;
if (!transactionInProgress)
{
transactionInProgress = true;
blankMask = B00000000;
for (int i = 0; i < 6; i++)
{
currentDigits[i] = fromStr.substring(i, i + 1).toInt();
toDigits[i] = toStr.substring(i, i + 1).toInt();
}
}
for (int i = 0; i < 6; i++)
{
if (iterationCounter < 10) currentDigits[i]++;
else if (currentDigits[i] != toDigits[i]) currentDigits[i]++;
if (currentDigits[i] == 10) currentDigits[i] = 0;
}
iterationCounter++;
if (iterationCounter == 20)
{
iterationCounter = 0;
transactionInProgress = false;
}
String tmpStr;
for (int i = 0; i < 6; i++)
tmpStr += currentDigits[i];
return tmpStr;
}

String updateDateString()
{
static unsigned long lastTimeDateUpdate = millis()+1001;
static String DateString = PreZero(day()) + PreZero(month()) + PreZero(year() % 1000);
static byte prevoiusDateFormatWas=value[DateFormatIndex];
if (((millis() – lastTimeDateUpdate) > 1000) || (prevoiusDateFormatWas != value[DateFormatIndex]))
{
lastTimeDateUpdate = millis();
if (value[DateFormatIndex]==EU_DateFormat) DateString = PreZero(day()) + PreZero(month()) + PreZero(year() % 1000);
else DateString = PreZero(month()) + PreZero(day()) + PreZero(year() % 1000);
}
return DateString;
}

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)

void SyncWithGPS()
{
if ((millis() – GPS_Date_Time.GPS_Data_Parsed_time) > 3000) {
Serial.println(F(“Parsed data to old”));
return;
}
Serial.println(F(“Updating time from GPS…”));
Serial.println(GPS_Date_Time.GPS_hours);
Serial.println(GPS_Date_Time.GPS_minutes);
Serial.println(GPS_Date_Time.GPS_seconds);

setTime(GPS_Date_Time.GPS_hours, GPS_Date_Time.GPS_minutes, GPS_Date_Time.GPS_seconds, GPS_Date_Time.GPS_day, GPS_Date_Time.GPS_mounth, GPS_Date_Time.GPS_year % 1000);
adjustTime((long)value[HoursOffsetIndex] * 3600);
setRTCDateTime(hour(), minute(), second(), day(), month(), year() % 1000, 1);
Last_Time_GPS_Sync = MillsNow;
GPS_Sync_Interval = GPS_SYNC_INTERVAL;
AttMsgWasShowed=false;

//// TIMEZONE add-ons
while (!Serial) ; // wait until Arduino Serial Monitor opens
//setSyncProvider(RTC.get); // the function to get the time from the RTC
//if(timeStatus()!= timeSet)
// Serial.println(“Unable to sync with the RTC”);
//else
// Serial.println(“RTC has set the system time”);

time_t utc = now();
time_t local = myTZ.toLocal(utc, &tcr);
Serial.println();
printDateTime(utc, “UTC”);
printDateTime(local, tcr -> abbrev);

setTime(myTZ.toLocal(utc, &tcr));
EEPROM.write(DateFormatEEPROMAddress, value[myTZ.toLocal(utc, &tcr)]);
//Serial.println(EEPROM.read(HourFormatEEPROMAddress));// check whether the new timezon’s winter /summer time is put in memory
//setTime(hour(), minute(), second(), value[DateDayIndex], value[DateMonthIndex], 2000 + value[DateYearIndex]);
//EEPROM.write(DateFormatEEPROMAddress, value[DateFormatIndex]);

//// End of TIMEZONE add-ons

 

}

void GetDataFromSerial1()
{
if (Serial1.available()) { // If anything comes in Serial1 (pin 19)
byte GPS_incoming_byte;
GPS_incoming_byte = Serial1.read();
//Serial.write(GPS_incoming_byte);
GPS_Package[GPS_position] = GPS_incoming_byte;
GPS_position++;
if (GPS_position == GPS_BUFFER_LENGTH – 1)
{
GPS_position = 0;
// Serial.println(“more then BUFFER_LENGTH!!!!”);
}
if (GPS_incoming_byte == 0x0A)
{
GPS_Package[GPS_position] = 0;
GPS_position = 0;
if (ControlCheckSum()) {
if (GPS_Parse_DateTime()) SyncWithGPS();
}

}
}
}

bool GPS_Parse_DateTime()
{
bool GPSsignal = false;
if (!((GPS_Package[0] == ‘$’)
&& (GPS_Package[3] == ‘R’)
&& (GPS_Package[4] == ‘M’)
&& (GPS_Package[5] == ‘C’))) {
return false;
}
else
{
// Serial.println(“RMC!!!”);
}
//Serial.print(“hh: “);
int hh = (GPS_Package[7] – 48) * 10 + GPS_Package[8] – 48;
//Serial.println(hh);
int mm = (GPS_Package[9] – 48) * 10 + GPS_Package[10] – 48;
//Serial.print(“mm: “);
//Serial.println(mm);
int ss = (GPS_Package[11] – 48) * 10 + GPS_Package[12] – 48;
//Serial.print(“ss: “);
//Serial.println(ss);

byte GPSDatePos = 0;
int CommasCounter = 0;
for (int i = 12; i < GPS_BUFFER_LENGTH ; i++)
{
if (GPS_Package[i] == ‘,’)
{
CommasCounter++;
if (CommasCounter == 8)
{
GPSDatePos = i + 1;
break;
}
}
}
//Serial.print(“dd: “);
int dd = (GPS_Package[GPSDatePos] – 48) * 10 + GPS_Package[GPSDatePos + 1] – 48;
//Serial.println(dd);
int MM = (GPS_Package[GPSDatePos + 2] – 48) * 10 + GPS_Package[GPSDatePos + 3] – 48;
//Serial.print(“MM: “);
//Serial.println(MM);
int yyyy = 2000 + (GPS_Package[GPSDatePos + 4] – 48) * 10 + GPS_Package[GPSDatePos + 5] – 48;
//Serial.print(“yyyy: “);
//Serial.println(yyyy);
//if ((hh<0) || (mm<0) || (ss<0) || (dd<0) || (MM<0) || (yyyy<0)) return false;
if ( !inRange( yyyy, 2018, 2038 ) ||
!inRange( MM, 1, 12 ) ||
!inRange( dd, 1, 31 ) ||
!inRange( hh, 0, 23 ) ||
!inRange( mm, 0, 59 ) ||
!inRange( ss, 0, 59 ) ) return false;
else
{
GPS_Date_Time.GPS_hours = hh;
GPS_Date_Time.GPS_minutes = mm;
GPS_Date_Time.GPS_seconds = ss;
GPS_Date_Time.GPS_day = dd;
GPS_Date_Time.GPS_mounth = MM;
GPS_Date_Time.GPS_year = yyyy;
GPS_Date_Time.GPS_Data_Parsed_time = millis();
//Serial.println(“Precision TIME HAS BEEN ACCURED!!!!!!!!!”);
//GPS_Package[0]=0x0A;
return 1;
}
}

uint8_t ControlCheckSum()
{
uint8_t CheckSum = 0, MessageCheckSum = 0; // check sum
uint16_t i = 1; // 1 sybol left from ‘$’

while (GPS_Package[i] != ‘*’)
{
CheckSum ^= GPS_Package[i];
if (++i == GPS_BUFFER_LENGTH) {
//Serial.println(F(“End of the line not found”)); // end of line not found
return 0;
}
}

if (GPS_Package[++i] > 0x40) MessageCheckSum = (GPS_Package[i] – 0x37) << 4; // ASCII codes to DEC convertation
else MessageCheckSum = (GPS_Package[i] – 0x30) << 4;
if (GPS_Package[++i] > 0x40) MessageCheckSum += (GPS_Package[i] – 0x37);
else MessageCheckSum += (GPS_Package[i] – 0x30);

if (MessageCheckSum != CheckSum) {
//Serial.println(F(“wrong checksum”)); // wrong checksum
return 0;
}
//Serial.println(“Checksum is ok”);
return 1; // all ok!
}

boolean inRange( int no, int low, int high )
{
if ( no < low || no > high )
{
Serial.println(F(“Date or Time not in range”));
//Serial.println(String(no) + “:” + String (low) + “-” + String(high));
return false;
}
return true;
}

#endif

String updateTemperatureString(float fDegrees)
{
static unsigned long lastTimeTemperatureString=millis()+1100;
static String strTemp =”000000″;
if ((millis() – lastTimeTemperatureString) > 1000)
{
//Serial.println(F(“Updating temp. str.”));
lastTimeTemperatureString = millis();
int iDegrees = round(fDegrees);
if (value[DegreesFormatIndex] == CELSIUS)
{
strTemp = “0” + String(abs(iDegrees)) + “0”;
if (abs(iDegrees) < 1000) strTemp = “00” + String(abs(iDegrees)) + “0”;
if (abs(iDegrees) < 100) strTemp = “000” + String(abs(iDegrees)) + “0”;
if (abs(iDegrees) < 10) strTemp = “0000” + String(abs(iDegrees)) + “0”;
}else
{
strTemp = “0” + String(abs(iDegrees)) + “0”;
if (abs(iDegrees) < 1000) strTemp = “00” + String(abs(iDegrees)/10) + “00”;
if (abs(iDegrees) < 100) strTemp = “000” + String(abs(iDegrees)/10) + “00”;
if (abs(iDegrees) < 10) strTemp = “0000” + String(abs(iDegrees)/10) + “00”;
}

#ifdef tubes8
strTemp= “”+strTemp+”00”;
#endif
return strTemp;
}
return strTemp;
}

float getTemperature (boolean bTempFormat)
{
static float fDegrees;
static int iterator=0;
static byte TempRawData[2];
/*unsigned long execTime=0;
execTime=micros();*/
switch (iterator)
{
case 0: ds.reset(); break;
case 1: ds.write(0xCC, 0); break; //skip ROM command
case 2: ds.write(0x44, 0); break; //send make convert to all devices
case 3: ds.reset(); break;
case 4: ds.write(0xCC, 0); break; //skip ROM command
case 5: ds.write(0xBE, 0); break; //send request to all devices
case 6: TempRawData[0] = ds.read(); break;
case 7: TempRawData[1] = ds.read(); break;
default: break;
}

if (iterator == 7)
{
int16_t raw = (TempRawData[1] << 8) | TempRawData[0];
if (raw == -1) raw = 0;
float celsius = (float)raw / 16.0;
//celsius = celsius + (float)value[TempAdjustIndex]/10;//users adjustment

if (!bTempFormat) fDegrees = celsius * 10;
else fDegrees = (celsius * 1.8 + 32.0) * 10;
}
/*execTime=micros()-execTime;
Serial.print(iterator);
Serial.println(execTime);*/
iterator++;
if (iterator==8) iterator=0;
return fDegrees;
}

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ISR(TIMER4_COMPA_vect)
{
sei();
doIndication();
}

void timerSetup()
{
//timer3 setup for calling doIndication function
TCCR4A = 0; //control registers reset (WGM21, WGM20)
TCCR4B = 0; //control registers reset
TCCR4B = (1 << CS12)|(1 << CS10)|(1 << WGM12); //prescaler 1024 and CTC mode
//OCR5A = 31; //2 mS
TCNT4=0; //reset counter to 0
OCR4A = 46; //3mS
//OCR4A = 92; //6mS
TIMSK4 = (1 << OCIE1A);//TIMER3_COMPA_vect interrupt enable
sei();
}
#endif

void testDS3231TempSensor()
{
int8_t DS3231InternalTemperature=0;
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(0x11);
Wire.endTransmission();

Wire.requestFrom(DS1307_ADDRESS, 2);
DS3231InternalTemperature=Wire.read();
Serial.print(F(“DS3231_T=”));
Serial.println(DS3231InternalTemperature);
if ((DS3231InternalTemperature<5) || (DS3231InternalTemperature>60))
{
Serial.println(F(“Faulty DS3231!”));
for (int i=0; i<5; i++)
{
tone1.play(1000, 1000);
delay(2000);
}
}
}

Mazda 3 2004 hatchback vervangen voorspatborden

Voorschermen vervangen en in Mazda  kleur A75 gezet:

Rechts op de foto zie je de onderkant van het spatbord, helemaal rot door het blad dat zich onderin ophoopt..
Wielen eraf en op de autobokken gezet.
Spatborden eraf en daarna de kokerbalk en dorpel gerepareerd (zie ander artikel)

 

Roestschade onderaan
Roestschade spatbordrand
Roestschade andere kant

2 nieuwe voorschermen besteld

2k epoxy etchprimer (MIPA)
2 lagen A75 (Mazda) metallic basislak.  Deze droogt mat op.
Met 600 waterproof tussendoor geschuurd en gereinigd, daarna weer rode basislak

En daarna 2 lagen 2K clearcoat en een verdunde wetcoat eroverheen

2 dagen uitharden
Rechts alles in de ML gezet, ook de kokerbalken waaronder die in de motorruimte.  Daarna de spatborden er op, koplampen monteren, voorbumper weer monteren, modderkuipen er weer in.  Daarna de bescherm strips  onder de dorpels er weer op enzovoorts.
Klaar, na het reinigen en in de was zetten van de auto.

Mazda 3 2004 hatchback reparatie kokerbalk en dorpel

De rechter dorpel en daarachter de dragende kokerbalk hersteld:

Roestschade rechter dorpel en daarachter ook aan de kokerbalk. Zie ook helemaal rechts de verroeste onderkant van het rechter voorscherm.

In de dorpels en in de kokerbalken alles over de hele lengte afgewerkt met de hogedruk tectylspuit met ML oplossing.  (Beide kanten)
Dit komt onder de kunststof afwerk/beschermstrip maar toch even in de juiste kleur gespoten.

De kokers, dorpels binnenzijde en alle open delen aan de onderkant zijn in de ML gespoten.

Stroomverbruik thuis managen met AR12DX meetmodulen / lastafschakelaars / prioriteitsschakelaars in de groepenkast

Na mijn installatie van twee 400 Volt krachtgroepen waarvan één voor laden van de elektrische auto en één voor de instant doorstroomboiler (om te douchen zonder gas) kwam ik in de knel met het stroomverbruik op een standaard 3×25 Ampère huisaansluiting.

Voor het laden van de auto was een gemakkelijke oplossing: Een load-balancer in de meterkast installeren of ernaast met een koppeling naar de slimme stroom meter van de netbeheerder  (een en ander afhankelijk van het gekozen merk laad-doos/paal) .  Vervolgens communiceert de load-balancer met de laadpaal hoeveel stroom er beschikbaar is voor laden van de auto.  Altijd goed zo.

Voor de krachtgroep van de doorstroomboiler was het moeilijker. Dit apparaat gebruikt 11 kW over 3 fasen verdeeld. Omdat we ook op 2 fasen koken en een warmtepomp gaan bestellen, wordt de belasting per fase mogelijk meer dan de geleverde 25 Ampère ofwel 5750 Watt.  Maal drie is dan 17250 Watt.

Je kan natuurlijk allerlei dingen afspreken met de medebewoners zoals niet douchen wanneer je kookt of wanneer de warmtepomp aan gaat.

Maar om er zeker van te zijn dat je verbruik niet opeens te hoog is kun je ook een technische oplossing maken die in je bestaande meterkast past.  Misschien passen de benodigde schakelmodules zelf wel in je bestaande groepenkast.   Bij mij paste het toevallig allemaal wel, omdat ik net een nieuwe groepenkast heb geplaatst voor de 400V krachtgroep om de elektrische auto te laden,.

De benodigde modules die je in de meterkast kan monteren zijn meetmodules die, wanneer je meer dan een instelbare waarde stroomverbruik van een bepaalde groep hebt, een schakelcontact kunnen bekrachtigen.  Via dat contact kun je dan een relais sturen dat ik in mijn geval tussen de voedingsaansluiting van de doorstroomboiler krachtgroep heb geplaatst.

Dat relais dat in de boileraansluiting is opgenomen, ie van het type Normal Connect, dus in de niet-actieve stand staat de doorstroomboiler gewoon onder spanning.

Als er van ten minste één  meetmodule een contact activeert, wordt het relais in de boileraansluiting geactiveerd en schakelt deze de doorstroomboiler UIT.

Technische_fiche_AR12DX

Ik heb in de 3 groepen L1, L2 en L3 ieder 1 stuks AR12DX schakel/meetmodule opgenomen en daar heb ik achtereenvolgens de volgende veelgebruikende ‘met prio’-groepen  aangesloten:

  1. Vaatwasser met elektrische keukenkraan (1-fase doorstroomboiler);
  2. Woonkamer, eerste verdieping, wasmachine en warmtepompdroger;
  3. Tweede kookgroep (onze 2-fase kookplaat kan ook op 1 fase werken).

Deze 3 groepen blijven altijd gewoon (dat heet in dit geval ‘met prio’) aan, ze bepalen alleen dat de douche-doorstroomboiler niet kan werken als er een bepaald vermogen op één van deze 3 groepen wordt overschreden.

De meet/schakelmodules zijn nl. instelbaar op afvalhysteresis (op 0 zetten voor deze situatie met gewoon contactrelais) en stroom.  De stroom waarop het contact wordt geactiveerd is instelbaar.  Dat is vooral bij groep 2) fijn, want bij gewoon TV kijken of verlichting aan wil je nog niet dat de schakelaar om gaat.

Ik heb de stroom van de tweede meet/schakelmodule op 5 Ampère gezet, van nummer 1 en 2 staat de stroominstelling op 1,5 Ampère.

Ik ben nog op zoek naar een 3-fase NC SSR, 400V 40A.  Als ik die heb vervang ik het relais.  Dat relais werkt erg goed maar het is ook erg luid.  De meterkast zit in de gangkast tegen de keuken.  De groepenkast zit op een houten plaat op het gipsen muurtje aan de andere kant van van de keuken en je hoort het relais heel goed schakelen.

Het schema van de 3x AR12DX meet/schakelmodules zoals ik het heb uitgevoerd: (nog in klad maar wel OK)

Tot nu werkt alles prima, de eerste week gebruik ook alles OK!

Ik heb wel de kookgroep ongebouwd naar een 2-fase aansluiting met een gewone 3-fase krachtsroom automaat.  Dan heb je voor beide aan te sluiten fases maar 1 maal een nul nodig.  Dat is ook met een Perilex stekker aan te sluiten.  Als je 2x 230 doet kan dat ook, beide 16 Ampère maar dan werkt dat niet samen met 2 maal een aardlekschakelaar, één per fase. Tenzij je dezelfde fase aansluit zoals kennelijk veel voorkomt.

Mijn kookplaat kan ook gewoon op 2 fases met aparte aardlek maar dan zonder Perilex stekker omdat je van beide groepen (en dus verschillende fases) ook de nul apart moet aansluiten.

Bij krachtstroom of 2x 230Volt van dezelfde fase moet je beide nul-aansluitingen juist doorverbinden.

In het plaatje hieronder is de linkse blauwe krachtstroom groep voor 2 groepen koken in gebruik.  Je kan de kabel 5-polig houden en in de Perilex wancontactdoos alles netjes afwerken op 3 fasen, nul en aarde.

Maar je kan ook 2 fasen, nul en aarde aansluiten mits je dat op de juiste te gebruiken punten aansluit, waar ook het kookapparaat de aansluitingen heeft zitten.

Dat zal meestal L1 en L2 zijn in de Perilex stekker van de kookplaat.  Handig is het dan om in het stopcontact  (Perilex wandcontactdoos) als je met twee ‘hete’ draden de 2 groepen aansluit, deze op L1 en L2 aan te sluiten.

En zó is de groepenkast uiteindelijk geworden

Van het gas af – vergelijkingsberekening tussen aardgas en electriciteit per 1-1-2023

De vergelijkingsberekening tussen aardgas en elektriciteit per 1-1-2323

Een m3 (kubieke meter) aardgas heeft een nuttige energetische inhoud van 8 kWh (bij een omzettingsrendement van gas naar warmte van 80% bij gebruikmaking van een  reguliere HR CV-ketel.

Een m3 aardgas kostte in augustus 2022 bij Essent met ons variabel contract Eur 2,40.

Het aardgastarief wordt door de regering per 1-1-2023 gemaximeerd op € 1,45 per kuub tot een verbruik van 1.200 kuub per jaar.

Een kWh (kilowattuur) elektriciteit heeft een nuttige energetische inhoud van 1 kWh (bij een reguliere omzettingsrendement van elektriciteit naar warmte van nagenoeg 100%).

Een kilowattuur elektriciteit kostte met ons variabel contract in augustus 2022 Eur 0,50.

Het elektriciteitstarief wordt door de regering per 1-1-2023 gemaximeerd op € 0,40 per KWh en het maximale verbruik wordt verhoogd tot 2.900 kWh per jaar.

Voor de vergelijking: Aardgas levert per m3 de gelijke energetische waarde van 8 kilowattuur elektriciteit. Theoretisch zelfs 10 kWh maar dat haal je in de praktijk niet gemakkelijk, daarom reken ik hier met 8 kWh.

Lees ook dit rapport: Vergelijking-aardgas-met-elektriciteit

In bovenstaand overzicht is duidelijk gemaakt dat de verhouding in energetische waarde tussen aardgas en elektriciteit een factor 10 op 1 is.

Vanwege de energetische omzettingswaarde van aardgas in een HR-ketel met een gemiddelde C.V. huisinstallatie, allebei van goede kwaliteit gaan we voor de vergelijking voor dit artikel uit van een energetische eindverhouding tussen aardgas en elektriciteit van 8 op 1  (1 m3 aardgas = 8 kWh elektriciteit).

De financiële berekening voor de vergelijking in energetische energie bij 1 m3 aardgas is dan vanaf 1-1-2023 bij een normwaarde van 1 m3 aardgasverbruik, exclusief vaste toeslagen:

  • Eur 3,20 kosten elektriciteit voor 8 kWh x Eur 0,4;
  • Eur 1,40 Kosten aardgas voor 1 m3 x Eur 1,40.

Je ziet dus dat aardgas voor verwarming per 1-3-2023 goedkoper is dan elektriciteit, wanneer je tenminste gewoon voor de elektriciteit betaalt en met normale elektrische verwarming werkt zoals keramische kachels enz. Salderen met zonnepanelen verandert de zaak.

Bovenstaande rekensom is natuurlijk erg afhankelijk van de geldende energieprijzen.

Het wordt wel extra gemakkelijk om over te stappen op elektriciteit wanneer je genoeg zonnepanelen hebt, en dat daarbij salderen nog steeds mogelijk is.

Overigens kun je ook qua verbruik nog behoorlijk besparen wanneer je je elektrische energie inzet met een warmtepomp of met airco met warmtepomp.  Daarbij kan het rendement op gebruik van elektriciteit nog met een factor 3 tot 5 verbeteren.

Van het gas af – hoge gasprijzen, gebruik zonnepanelen, warmtepomp en airco, keramische-en LPG kachels

an-het-aardgas-af-hoge-gasprijzen-gebruik-zonnepanelen-keramische-en-lpg-kachels

Vanwege de hoge gasprijzen, het per saldo meer elektriciteit terug leveren dan we verbruiken en vanwege het feit dat we eigenlijk sowieso minder van aardgas afhankelijk willen zijn hebben we naar alternatieven voor het gebruik van aardgas gezocht.

Quote uit overstappen.nl van 9-9-2022: In augustus 2021 was de gemiddelde gasprijs nog 0,95 euro per m3 gas. In 2022 is de gasprijs flink opgelopen. Momenteel betreft de gasprijs gemiddeld 3,94 euro per m3. Dit tarief is inclusief energiebelasting, ODE en 9% BTW.

Twee van de genoemde alternatieven hebben we al ingevuld, namelijk de elektrische doorstroomkraan in de keuken en de elektrische krachtstroom doorstroomboiler om te douchen (en voor de wastafel in de doucheruimte).

Het derde besparingsalternatief is om zo veel als mogelijk te besparen op de verwarmingskosten. Dat staat beschreven in het betreffende artikel.

De motivatie om deze alternatieven voor aardgas te installeren en te gebruiken zijn voor een groot deel gebaseerd op de situatie van de hoge prijzen voor aardgas en -in mindere mate- van elektriciteit., en natuurlijk zijn we ook gedreven door het feit dat we uiteindelijk met z’n allen van aardgas af moeten en renewable of op z’n minst sustainable energie willen gebruiken.

Warmtepomp wel de beste oplossing, maar…

https://www.gasvrij.nu/de-cop-van-een-warmtepomp-uitgelegd/#:~:text=De%20COP%2Dwaarde%20geeft%20aan,4%20kWh%20aan%20warmte%20terug.

In bovenstaand artikel dat we hebben overgenomen van gasvrij.nu kun je lezen dat een warmtepomp in het meest ideale geval een COP waarde van 4 tot 7 kan hebben. Dat betekent dat je een betere energetische waarde (ter vergelijking) ten opzichte van de benodigde erin te stoppen elektrische energie kan bereiken van een factor 4 tot 7.

Ter vergelijking: Aardgas staat op een maximale theoretische energetische waarde van 8x t.o.v. electriciteit en het is dus niet zo gek dat we aardgas zo lang hebben gebruikt. Zeker als je naar de oude tarieven kijkt was aardgas wel tot 10x goedkoper om te verwarmen dan met electriciteit, Nu is die factor 2x goedkoper, LEES HIER.

Met een warmtepomp ben je eigenlijk dus gewoon het beste af wanneer je van aardgas af wilt.  Maar de benodigde ruimte, herrie en kosten van installatie en onderhoud zijn allemaal belemmeringen waarom wij er nog niet voor hebben gekozen. Terwijl we heel goed weten dat we dat uiteindelijk wel moeten doen.

 

De COP factor van een airco warmtepomp

De COP factor is de verhouding tussen de elektrische energie die de airco verbruikt in verhouding tot de warmte die verplaatst wordt. Wanneer een airco bijvoorbeeld 500 Watt verbruikt maar in staat is om 2000 Watt aan warmte te verplaatsten dan is de COP-factor 2000 / 500 = 4. Tegenwoordig is een COP-factor van 4 heel normaal. Hoe hoger de COP-factor is, hoe zuiniger de airco is. Op het moment van schrijven zijn airco’s te koop met een COP-factor van 5,6. Heb je de keus tussen twee modellen en de COP factors zijn 4,3 en 4,8 dan heeft het model met een COP factor van 4,8 een duidelijk voorkeur ook al is dat model stukken duurder. De energie-winst die je tijdens de levensduur van de airco zal behalen zal de extra kosten ruimschoots compenseren.

COP waarde is niet constant

De opgegeven COP-waarde is alleen maar van toepassing bij een bepaald verschil tussen de buiten- en binnentemperatuur. De COP-factor neemt namelijk af als het verschil tussen de binnen en buitentemperatuur stijgt. Heeft een airco een COP-factor van 5 bij een buitentemperatuur van 10° Celsius dan daalt de COP-waarde naar bijvoorbeeld 3,5 als het buiten 0° Celsius is. Ondanks deze lagere prestatie blijft het nog steeds interessant om een airco in te zetten als verwarming.

De situatie

Onze Nefit HR-ketel draait uiteraard op aardgas.

We hebben al ruim 5 jaar 9 zonnepanelen op ons dak liggen en we verbruiken ook op jaarbasis veel minder stroom dan we terug leveren.

We schakelen overal alle apparaten uit, ook alle opladers en TV, stereo en zelfs de internet installatie gaat zover mogelijk ’s nachts uit.  Behalve het internet modem natuurlijk en de internet server.  Ook de C.V. ketel staat uit wanneer we deze niet gebruiken.  Dat scheelt echt veel, want de C.V. ketel verbruikt altijd energie, ook wanneer je deze niet gebruikt.  En als we kunnen douchen met water van een elektrische doorstroomboiler gaat het aardgas  en de C.V. ketel in de zomermaanden helemaal uit.

Het aardgas kostte de afgelopen maand, augustus 2022, met ons variabel contract bij Essent bijna 4 Euro per m3 (kuub, kubieke meter in gasvorm).

Een Kwh elektrisch verbruik kost ca. 1 Euro op dit moment en een teruggeleverde Kwh levert 0,055 Euro op (5,5 Eurocent).

Omdat we altijd veel meer elektriciteit terug leveren dan verbruiken gaan we alle mogelijke moeite doen om alles dat kan elektrisch te doen.  Door te salderen kunnen we dan eindelijk beter gebruik gaan maken van onze 9 zonnepanelen!

 

Uiteindelijk is alles tijdelijk, en is alles mogelijk. En dat we van het aardgas af moeten is onontkoombaar.  Tegen welke kosten weten we nog niet, maar voor je eigen situatie kun je wel alvast de nodige dingen aanpakken. Waarbij je niet nu al het aardgas helemaal de deur uit hoeft te doen.  Alleen al het verbruik sterk verminderen help behoorlijk.  Ook in je eindafrekening.

De ontwikkeling van alternatieven gaat namelijk maar moeizaam en de verkrijgbaarheid van alternatieven is beperkt.

Wat mij betreft dus hoog tijd voor een meer persoonlijke aanpak!  Hoe meer mensen meedoen des te meer druk komt er op de leveranciers- en ontwikkelingsmarkt om met meer- en met nieuwe producten te komen.

Succes met je zoektocht en bookmark ons voor komende updates:

 

Van het gas af – Elektrisch bijverwarmen of toch aan de warmtepomp?

In dit artikel beschrijven we onze oplossing om ons aardgasverbruik in de komende winter ’22-’23 met ten minste 50% te reduceren.

Het oorspronkelijke plan:

  • een deel van het huis niet meer verwarmen;
  • per ruimte waar nodig bijverwarmen met elektrische keramische 500 Watt muurstekker kacheltjes met thermostaat;
  • beneden in de woon/kookruimte primair met een LPG gestookte potkachel de ruimte verwarmen, eventueel aangevuld met 2 stuks keramische kacheltjes, met thermostaat.
LPG gestookte potkachel met katalysator, zuurstofsensor enz.
thermostatisch geregelde elektrische mini bijzetverwarming 500 Watt

Toch nog even nadenken..

Maar als je gaat rekenen met energetische waarden en prijzen van elektriciteit kom je er al snel achter dat zo’n oplossing met elektrische bijverwarming niet erg haalbaar is.

Elektrisch verwarmen is gewoon niet erg economisch omdat het ondanks de hoge energieprijzen nog steeds 2x duurder is om elektrisch te verwarmen ten opzichte van verwarmen met aardgas.  (kort door de bocht: 1 m3 aardgas van Eur 4 per m3  levert evenveel  energetische energie als 8 kWh elektriciteit van Eur 1 per kWh en 4 Euro is de helft van 8 Euro)

De warmtepomp installatie in plaats van de gasgestookte C.V. ketel

Als de energieprijzen zo hoog blijven als in augustus 2022, gaan we dus z.s.m. een volledige elektrische warmtepomp installatie plaatsen met split units.

Dan gaan we gelijk helemaal van de gasgestookte CV HR ketel af. want we hebben al een lage temperatuur C.V.  systeem met vloerverwarming.

En dat is extra handig bij het inzetten van een warmtepomp installatie:

Split-buitenunit (links) en de binnenunit (rechts) met 12.6 kW verwarmingsvermogen voor een volledig elektrisch werkend warmtepompsysteem zonder gasgestookte C.V. ondersteuning.

Het wordt dus geen hybride systeem, waarbij de gasgestookte C.V. ketel blijft zitten en bijspringt wanneer het kouder wordt dan ca. -5 graden.

Dan kom je nooit van het gas af, want heb je gewoon een te kleine warmtepompinstallatie om zonder de C.V. ondersteuning verder te kunnen wanneer het gas er ooit af gaat, of je er gewoon af wilt.

Bij een hybride warmte pomp installatie moet de gasgestookte C.V. ketel bijspringen wanneer het te koud wordt (buiten onder -5 graden) of als je te lang niet gestookt hebt en het daardoor zonder het bijspringen van de gasgestookte C.V. ketel veel te lang duurt voor het een beetje warm wordt.

Tot 6-8 kW zijn er hybride systemen die samenwerken met de bestaande C.V. ketel.  Als je een systeem wilt hebben dat de gasgestookte C.V. ketel kan vervangen moeten we even rekenen welke afgegeven waarde aan warmte we precies nodig hebben.

De bestaande gasgestookte HR C.V. ketel is een Nefit smartline HRC24 CW4.  Die heeft een afgegeven vermogen (max) van 24kW.

Onze warmtepomp moet volgens de kenners ten minste een SCOP waarde hebben van een factor 5.

Dat betekent dat de elektrische energie die je in de warmtepomp installatie stopt voor het transport van energie er voor zorgt dat er binnen 5 maal meer energie aan ( warm C.V.-) water van max. 55 graden Celsius wordt afgegeven.

Dat komt door het werkingsprincipe van de warmtepomp, net als bij condens(was)drogers en airco’s met warmtepomp principe.

Als het buiten kouder wordt dan wordt het rendement van de warmtepomp qua verwarmen wel minder.

Dus voor een warmteafgifte van 24 kW heb je een warmtepomp systeem nodig dat 24kW energetisch kan afgeven aan waterwarmte.   En dat systeem verbruikt daarvoor 24/5 = ongeveer 5 kW aan elektriciteit  bij een SCOP waarde van 5.

Omdat dergelijke warmtepomp systemen gebaseerd zijn op standaard aansluitingen met de 230Volt netvoorziening met 16 Ampère aansluitwaarde, zijn de gangbare warmtepompsystemen meestal iets kleiner dan 24kW.  De door ons geselecteerde waarde van het split systeem is 12,6 kW.  Daarmee blijft het opgenomen elektrisch vermogen ruim binnen de 16 Ampère norm van de aansluitwaarde van de elektrische groepen in onze woning.

Het zou kunnen dat we bij strenge vorst een probleem hebben om het huis echt warm te stoken, dat nemen we op de koop toe.  Als we met de installateur/leverancier praten over het toe te passen warmtepomp systeem zullen we ook nog even laten doorrekenen of het allemaal wel goed gaat met een 12,6 kW systeem. En desnoods kiezen we voor een iets groter systeem.

De split buitenunit komt op het platte dak, ergens tussen de zonnepanelen of op het schuine dak, net onder het dakraam met speciale schuine dak beugels voor ons schuine dak.  Het moet sowieso een stil model worden, dat wordt mogelijk nog lastig want dat zijn dit soort buitenunits eigenlijk nooit.  Er moet dus ook een nachtstand op zitten met gereduceerd pomp- en ventilator gebruik.

Mogelijk plaatsen we gelijk een tussenboiler binnen bij de binnen-unit,  zodat er altijd een voorraadje warm water is.  Als we daarmee kunnen douchen kan de doorstroomboiler uit en gebruiken we de doorstroomboiler alleen als het buiten te koud wordt.

De kosten zijn ca 7500 Euro voor deze installatie en dat hebben we er wel voor over.  Dan krijg je ook nog ca 2500 Euro subsidie achteraf terug.

De isolatie van ons rijtjeshuis is trouwens ook prima, en we zijn al heel tevreden als de warmtepomp zodanig werkt dat de begane grond op 20 graden kan worden verwarmd. De slaapkamers willen we gemiddeld op 15 graden houden.  De 2e verdieping gaat op de antivorst stand..

En over terugverdienen denk ik ook helemaal niet na.

We moeten sowieso van het gas af, en onze C.V. ketel is nu 20 jaar oud, er is al van alles aan vervangen en het werkt allemaal elke keer na de reparatie weer prima.

Maar vervanging komt er wel aan.

En of dat wel zo handig is , gezien de wens om juist van het gas af te komen?

Dan liever maar gelijk goed aanpakken.

Koelen met de C.V. installatie en de warmtepomp kan ook

Overigens wil ik gelijk een warmtepomp systeem dat ’s zomers actief kan koelen.

Bij een volledig elektrisch warmtepomp systeem is dat in principe goed mogelijk.

De radiatoren worden dan koud.

Dat lijkt een hele handige optie, ik ben wel benieuwd hoe mijn thermostaatkranen daar mee om gaan!

Onze verwarmingssituatie

Ons huis heeft nu nog o.a. op de begane grond een met de C.V. direct gestookte vloerverwarming en op alle verdiepingen geïsoleerd glas. De spouwmuren zijn nog zonder isolatie (daar moeten we eigenlijk wat aan doen maar het muuroppervlak is in verhouding tot de ramen zo klein dat het effect van muurisolatie waarschijnlijk niet heel groot is, volgens de kenners…) en we hebben een zolder die niet als slaapkamer wordt gebruikt.

De zolder gaan we dus sowieso niet warm stoken, en dat scheelt alweer een stukje.

En we koken al elektrisch, de oven is ook elektrisch.  De keukenkraan is elektrisch, en het douchewater (en wasbak) wordt via een 11kW doorstroomboiler ook al elektrisch verwarmd.

Warmtepomp of airco-installatie?

Een airco-installatie zou ook nog kunnen  natuurlijk, dat werkt ook met een warmtepomp principe. Op dit moment is het enige airco systeem dat qua rendement aardig OK is, en betaalbaar qua installatie een meervoudig aircosysteem met 1 unit buiten en meerdere units binnen.

Dan moet je wel een installatie hebben met een COP-waarde boven 5 want dan heb je ook wanneer het koud wordt nog een beetje rendement als je er ook mee wilt verwarmen.

Zo’n Multi-airco systeem met 4 binnen-units en 1 buitenunit met een COP-waarde van 5,5 heb ja al vanaf zo’n 5 tot 7 duizend Euro geïnstalleerd in  huis.  Of het allemaal wel mooi is, in elke ruimte zo’n airco aan de muur en buiten een grote unit aan de geven of op het schuine dak denk ik niet, maar den kunnen alle lelijke CV leidingen en radiatoren er tenminste wel uit.  Misschien zijn de gaten in de tussenvloeren dan wel te hergebruiken voor de airco-leidingen… Voordeel van zo’n jaren 80-huis: er zitten geen CV leidingen in de vloeren, alles zit in het zicht.

De prijs voor zo’n airco-installatie lijkt veel geld en dat is ook zo.

Een C.V. installatie is in na-aanleg overigens net zo kostbaar.

Om over het na-aanleggen van warmtepomp systemen in bestaande huizen nog maar niet te spreken, want dat gaat gauw over de 7500 Euro heen.  Maar je kan de radiatoren dan wel lekker allemaal laten zitten en gewoon de vloerverwarming blijven gebruiken. Dat lijkt me uiteindelijk de beste oplossing.

Maar even snel de prijzen en mogelijkheden van volledige lucht-warmte split units warmtepomp C.V.-installaties opvragen,  het lijkt me het beste om gelijk de juiste keuze te maken.

11-9-2022: Wordt vervolgd!

 

 

 

Van het gas af – Douchen met elektrische doorstroomboiler

Als je een goede elektrische boiler hebt kun je overdag in de ca. 8 zonmaanden voldoende elektriciteit van de zonnepanelen gebruiken om een elektrische boiler warm te krijgen, waarmee je vervolgens kan douchen.

Daarnaast (of in plaats van) kun je een 3-fase doorstroomboiler gebruiken wanneer de voorraadboiler leeg is.  Dan vul je in ieder geval de goedkope opslag van water vanaf de energie van de zonnepanelen aan met elektrische energie voor de doorstroomboiler, dat is nog altijd beter dan met de CV combiketel op aardgas.

Uitsluitend een doorstroomboiler is natuurlijk ook mogelijk.  Dat is qua ruimte wel de meest eenvoudige oplossing.

En zolang saldering nog mogelijk blijft is dit voorlopig waarschijnlijk ook de meest economische oplossing.

Voor nu gaan we uit van die situatie: Alleen een 3-fase doorstroomboiler.

Bijgaande boiler heb ik 15-9-2022 geïnstalleerd op zolder, om te douchen en voorwarm water van de wasbak in de doucheruimte.  De warmwater voorziening van de gasgestookte HR C.V. ketel heb ik afgesloten, en op de C.V. ketel heb ik de warmwaterknop op de 0-stand gedraaid.

We zien later wel of we ook nog een extra voorraadboiler zien zitten.

Om de doorstroomboiler op zolder naast de C.V. ketel te installeren is een 3 fase 5-polige aansluiting met 5×2.5 mm2 gemaakt.

Dat mag dus niet in een al bestaande buis, omdat er een NEN1010 norm is over de maximale hoeveelheid draden in 5/8 inch buis of flexbuis. Daarnaast is het niet toegestaan om verschillende 230V groepen of een combinatie van 230 Volt groep met 400V in één buis te installeren.

Dus is er een nieuwe installatie gedaan van een 3/4 inch buis vanuit de groepenkastaansluiting naar zolder tot naast de instant doorstroom boiler.

Daarvoor heb ik in beide verdiepingsvloeren gaten geboord naast de bestaande gaten van de C.V. leidingen. Deze C.V leidingen volgen aan de voorkant van het huis precies boven de meterkast hetzelfde pad als de nieuwe aanleg van de krachtstroom aansluiting.

Op zolder is een CEE form 16A krachtstroom wand-chassisdeel geplaatst en aan de doorstroom boiler heb ik een bijpassende stekker gemonteerd.

Omdat in de meterkast al een extra 400V krachtstroomgroep is geïnstalleerd hoefde ik na aanleg van de buis alleen nog maar de draden aan te sluiten op de voorbereide groep.

De Stiebel Eltron DCE 11/13 3-fase doorstroomboiler werkt prima! Ik heb de doorstroomboiler ingesteld op 11kW.

technische-gegevens Stiebel Eltron DCE 11/13

Na de installatie heb ik in de meterkast de bestaande groepenverdeling verwijderd en alles opnieuw verdeeld.  Daarbij heb ik 3 groepen met lastgebruik verdeeld over de 3 fases en elk van deze groepen via een lastschakelaar laten lopen.  Elke grootverbruiker schakelt daarmee boven een ingestelde verbruiksdrempel via een 4-fase NC relais de doorstroomboiler af. 

Doel is om de 3×25 Ampère aansluitwaarde van de woning niet te overschrijden.  Wanneer ja dat doet blaas je één of meerdere hoofdzekeringen op en moet je netbeheerder deze komen herstellen.  Meestal keuren ze dan gelijk je installatie (af).  en heb je er daarna alsnog veel werk aan.

Door mijn aanpassing kun je alleen douchen wanneer de volgende apparaten niet in gebruik zijn:   1) Vaatwasser, 2) wasmachine/droger, 3) 2e kookgroep.  Dat gaat bij ons prima.  Door deze schakeling blijf ik nu altijd binnen de 25Ampère laststroom per fase.

Het lijkt wat ingewikkeld maar als het er eenmaal in zit heb je er geen omkijken meer naar en het went snel. Bovendien wordt de douche niet de hele dag gebruikt! -)

De douchekraan wordt ongeveer even snel warm als met de CV ketel. En qua doorstroming is er helemaal geen probleem.  Warmte is meer dan voldoende en ik heb zelfs de knop van de doorstroomboiler teruggedraaid naar 50 graden.  Dat is in de praktijk ruim voldoende.

De doorstroomboiler is overigens maar een heel klein apparaat.  Het is eigenlijk gemaakt om in een keukenkastje onder de gootsteen te passen, en dan kan de afvalbak er nog gewoon in blijven. Omdat er geen boiler in zit, alleen maar wat elektronica en een verwarmingselement valt de afmeting erg mee.

 

 

Van het gas af – Instant verwarmde elektrische keukenkraan

We zijn in ieder geval in de keuken van het gas af.

Koken doen we al een tijd elektrisch en nu is de keukenkraan ook elektrisch!

En dat scheelt weer wat gasverbruik, omdat elke keer dat je warm water helemaal van zolder naar beneden moet laten opwarmen de ketel al die tijd vol staat te branden.

Dat kostte me afgelopen maand 4 m3 gas, buiten het douchen.

Maal ca.2 Euro per m3 bij Essent in de maand augustus 2022 dus met de huidige prijzen en ons variabele tarief.

Boven zie je de levering van de nieuwe elektrische kraan met doorstroomelement van 3500 Watt, 230 Volt.

https://nl.aliexpress.com/item/1005003640074943.html?spm=a2g0o.order_list.0.0.2fd379d2jApzll&gatewayAdapt=glo2nld

De foto is gemaakt nadat ik het geheel heb gedemonteerd vanwege de beschadigde buitenkant van de kraan (deukje!)

De kraan kan gelukkig helemaal uit elkaar, en ik heb de deukjes netjes kunnen terugdrukken met een lange staaf massief ijzer in de bankschroef.  De staaf is aan de bovenkant rond geslepen zodat je door steeds een klein stukje naar buiten weg te drukken alle beschadiging weg krijgt.  Gewoon spotrepair dus.

Daarna alles weer in elkaar gezet, de oude kraan verwijderd en de nieuwe erin.

De warmwater aansluiting heb ik afgedopt want de nieuwe kraan wordt alleen aangesloten aan de koudwater aansluiting en aan een vrije 230 Volt aansluiting.

De kraan heeft 3 functies:

  1. een koud water regeling van het midden naar helemaal links waarmee je de hoeveelheid koud water kan regelen.
  2. in de middenstand is de kraan dicht
  3. en naar rechts draaiend komt er van weinig to maximaal warm water uit.

Vanwege de constructie is mengwater niet mogelijk bij deze kraan.

Maar let op: Je regelt de temperatuur van het water als volgt: Hoe meer warm water, hoe minder warm.

En als je minder warm water gebruikt komt er dus gewoon minder water uit dat steeds heter wordt.

Dat is wel erg wennen.

Maar het went heel snel.

Als je iets warm af wil spoelen met een sponsje of doekje ben je geneigd om het water warm te willen hebben en draai je de kraan eerst iets te ver open, daarna iets dicht tot het te warm wordt, dan weer verder open enzovoorts.

Na een paar dagen heb ik gemerkt dat ik al aardig de temperatuur kan inschatten en steeds meer leer hoe je deze kraan moet gebruiken.

Maar in de praktijk kan deze elektrische doorstroomkraan gewoon niet meer verwarmen dan in de voluit stand,  en dat is net 40-43  graden.

Pas wanneer je de doorstroming verminderd wordt het water warmer.  Wel tot over de 60 graden, en dan heb je nog een redelijk straaltje over.  Maar voor de meeste toepassingen in de keuken is 40 graden meer dan genoeg.

Er bestaan ook elektrische doorstroom warmwaterkranen met zowel een warme bediening als een koude bediening. Daarmee kun  je dus ouderwets mengwater gebruiken en de temperatuur regelen.  Maar mengen met de koud water stroom bij zo’n kraan met 2 hevels (één voor warm water en één voor koud water) gaat niet lukken.

Daarvoor is de verwarming van 3500Watt niet voldoende zwaar om het water op te warmen.  En meer dan 3500 Watt past niet in de kraan maar past ook niet op het verbruik van de elektrische installatie.  3600 Watt is het maximum dat een 16 Ampère groep in een woning kan leveren.

We gaan het voorlopig zo proberen want ik wil geen boiler onder het aanrecht hebben die altijd water op voorraad verwarmt, ook wanneer we het niet nodig hebben.  Dat bespaart ook niet echt.

Nu hebben we ten minste alleen maar kort elektrisch verbruik wanneer we warm water tappen in de keuken.  want het water wordt nu heel snel warm, vergeleken met de oude situatie een hele verbetering.

In snelheid en gemak, maar hopelijk ook in gasverbruik.

Het resultaat!

Maar..

Uiteindelijk beviel de kraan toch niet echt, omdat de bediening te ingewikkeld is voor nieuwe gebruikers wordt er behoorlijk aan de kraan getrokken en daar kan deze niet echt tegen.

Dus na 2 weken maar een nieuwe mengkraan gemonteerd op de oude aansluitingen van warm en koud water.

Dan maak ik gelijk gebruik voor het warme water van de doorstroomboiler van de douche, dan moet je wel even wachten op warm water maar het is nog steeds zonder gasgebruik!

Webhosting thuis met een DS718+ Synology Webserver

De performance van mijn grotere sites liet nogal wat te wensen over, en de kosten lopen ondertussen behoorlijk op.  Ik had ruim 10 sites draaien, allemaal bij dezelfde provider en de kosten zitten per site tussen de 185 Euro per jaar en de 65 Euro per jaar.  Voor de grote sites heb ik 5GB opslag en de kleinste is 200MB.

HOMESERVER / thuisserver: Voorheen heb k al een paar websites vanuit huis gehost, op een Zyxel NAS met een goedkope domein provider.  Dat werkte toen allemaal prima.  Gebaseerd op mijn eerdere ervaringen heb ik een Synology DS718+ webserver (onderste van de onderstaande foto) aangeschaft, een paar snelle SSD’s met mirroring erin en maximaal RAM erbij.  De kosten bedragen ongeveer 800 Euro.  Als backup heb ik een DS218 play erbij (bovenste) , met een paar dikke harddisks erin en extra RAM als gewone lokale NAS met als extra een mirrored wordpress server er bij voor nood en bij onderhoud aan de hoofd server.

Inmiddels zie je dit bericht dus vanuit mijn thuis-server.

Mijn ervaring is dat het altijd beter is om als enige op je eigen webserver te zitten dan om shared hosting te huren, ongeacht de zogenaamde SSD-hosting et cetera.  Dat doen grotere bedrijven namelijk ook: Gewoon een dikke server aan een snelle internet connectie.

Ik heb er voor de zekerheid overigens wel een backup (UPS) met accu voor de 230 Volt power aan de internet modem/router en webservers zitten, en een data-connectie backup via een mobiele connectie, mocht de internet aansluiting onderuit gaan. De autonomie van de UPS is ongeveer 6 uur.

En.. of het bevalt?  Eigenlijk ben ik vooral heel blij met de samenvoeging van mijn verschillende sites naar 1 overall site vanwege de overzichtelijkheid.  Door mijn diversiteit aan interesses had ik gewoon te veel sites draaien waardoor de aandacht op de sites onvoldoende is geweest.  Nu ik er nog maar 1  heb  is alles veel simpeler geworden.

That’s it!

Dometic tropicool TC21FL stil gemaakt

Onlangs heb ik een draagbare dual power koelbox van Tropicool gekocht, 21 liter inhoud. Maar toen ik hem opstartte, was het geluid een beetje meer dan ik had verwacht.

Ik heb al een grotere ‘VRIJBUITER’ draagbare vriezer/koeler van 38 liter met een compressor die ik vorig jaar geluidloos heb gemaakt.

 

DC mini fridge/cooler - DC-40Y (China Manufacturer) - Refrigerator - Consumer Electronics &amp; Lighting Products - DIYTrade China manufacturers

This 40 liter machine had a 50mm (2 inch) fan to cool the condensor and I completely repositioned some movable parts to get a 120mm (4.8 inch) fan in the machine instead.  The 120 mm fan is a silent fan and this resulted in an almost silent and  better operating freezer/cooler.  But- this machine does not run on the car battery, only on A/C  230 Volts.

So- back to the Dometic machine:  This is the machine

At the front lower  part a large area shows a fan behind the plastic front.  A 12 Volts DC fan is positioned behind this front . The fan is managed by the electronics and only switches on and off. No PWM or similar technique is used.  This cooler is not working with a compressor but with a/some Peltier element(s) and cooling/heating radiators, so a big aluminium block needs to be cooled by the fan to get the machine to work (and cool or warm the inside).  This machine can either cool -25Deg C or warm +25Deg C the inside.  A failsafe mechanism prevents freezing and temperatures above 65 DegC.

The picture below shows the original fan below and the replacement fan above.

The original fan was IMHO rather loud at 53 dBm (at 50cm distance), I presume mainly due to its design.

On the net, I read that most users of this machine are pleased with it and don’t think it makes much noise.

But- I need to operate this in our rented place which can either be an apartment, B&B or hotel room during our visits so I want it to make as little noise as possible. The replacement fan is a ball-bearing super-silent PC fan and runs at 12 Volts.

The replacement was quite easy: Open the lower front by removing all crews around and bottom.  Disconnect the fan-connector from the electronics board.  Unscrew the old fan.  Screw the new fan in place.  Connect the new fan to the electronics board, replace the housing part and screw it back in place.

So- the result is that this cooler now actually works a lot more silent, AND a lot better.

I could not get a fixed dBm reading with my portable dB-meter due to the low noise level.

Cooling goes faster than before at about 30% as I measured it in difference in the before- and after situation in cooling to 5 degrees C from room temp of 25 deg C.  Another succesfull project!

We’ll see how we like this cooler during our short stay in France this summer, in Granville!  C) JG 2021-06-30.

Afterthoughts:  To be sure that the cooler is indeed super silent at night, I also put in a DC voltage regulator that can regulate the voltage for the fan between 5 V DC and V max (about 12Volt).

During oiur holiday in France, the machine worked awesome.

In the hotel, we experienced no disturbances from the cooler at all, nore in the car.

And it kept everyrhing cool without too much noise.

 

Hoekserre dak

14 maart 2020

Dit gaat ‘m worden:

 Een lariks houten frame met 3 lariks 15×15 cm palen, bevestigd aan de muren van 2 garages en daartussen een houten frame met 5×15 cm spantbalken.  Dus een open dak, zonder verticale frontpaal of -palen.

De voorste balken zijn bevestigd aan de hoeken van beide garages en met een lange schoorbalk verbonden met de dubbel uitgevoerde frontbalken.

De standaard enkele hoek aan de rechterzijde van een typisch serredak is aangepast naar twee hoeken van 45 graden zodat aan de rechter voorkant van het serredak een brede entree komt, zonder palen.  De reguliere linker voorkant van het dak staat op een paal tegen de linker garage aan (nr. 22).

Op het dak worden 16mm transparante kanaalplaten geplaatst, met aluminium afwerking rondom.

Aan de 2 lage zijden van het serredak komt een smalle 125 mm witte kanaal dakgoot ‘Nicoll Ovation’, deze heeft ook een 45 graden buitenhoek in het assortiment.

nicoll-ovation-wit-buitenhoekstuk-135

De bouwtekening:

Logistiek:  Eerst alle spullen bestellen en/of ophalen:

Het basis dakontwerp:

De eerste proefopzet van de schoren in plaats van verticale palen:

Om zeker te zijn dat de opzet gaat werken, heb ik eerst een proefbouw gedaan met lichter hout.  De draagkracht is groot, maar de gebruikte materialen buigen door wanneer ik veel gewicht in het midden van de constructie plaats.

Daarom is in de uiteindelijke versie gekozen voor een constructie met douglas lariks houten balken en palen waarop normaal gesproken een plat dak met mastiek kan worden gebouwd.

Dag 1: Het frame op maat maar nog los aan elkaar

Dag 2: Detail van de ingeklemde schoorbalk

Dag 2: De basisconstructie is klaar

De constructie is vrij dragend, waarbij de enige ankerpunten de 3 balken zijn die aan de muren van de garages zijn verankerd met pluggen en lange tellerkop schroeven.
De hele constructie is ingeklemd tussen beide garages dus is er geen mogelijkheid dat er iets los komt.  Alle balkverbindingen zijn gebout met 16 centimeter lange M10 slotbouten, ringen en borgmoeren.  De liggers zijn met raveeldragers en 5cm lange 5mm dikke zelfborende raveelschroeven bevestigd.  Alle houtverbindingen zijn daarnaast ook vastgeschroefd met lange zelfborende Tellerkop hout-constructieschroeven.

Dag 3: De liggers geplaatst en de eerste 2 kanaalplaten gemonteerd

Zoals je op de foto’s kan zien is het afschot naar rechts, de platen liggen ook van links naar rechts.
Het afschot is maar 4 cm per meter, anders komt de balk aan de rechterkant onder de 2 meter doorloophoogte.

Dag 4: Alle kanaalplaten geplaatst en alle afwerk profielen geplaatst, houtveredeling aangebracht

Dag 5: Met gemonteerde goot en (bijna) alles opgeruimd

Met regengoot

En  nog even zoals het was, met de oude stenen en de oude aanbouwtjes, op de foto allemaal gedemonteerd.
Let ook op alle begroeiing…Overzicht 2019 achtertuin, met de gesloopte opslag nog in de tuin

Ga voor het bestel- en kostenoverzicht HIERHEEN

En met de afdichting er omheen: