Fórum témák

» Több friss téma
Fórum
Keresés
Lapozás: OK   21 / 56
(#) kameleon2 válasza bakos13gab hozzászólására (») Júl 18, 2016
Már évek óta 32A jár alanyi jogon. Akár meg is osztható több fázison.
(#) bakos13gab válasza papo69 hozzászólására (») Júl 18, 2016
Én tavaly előtt megkérdeztem az ügyfélszolgálaton, mert a közeljövőben bővíttetnék és azt mondta az ügyintéző, hogy kérvényezem és kijönnek, cserélnek. 32A-hez kell a szakvélemény. De lehet vagy nem mondta jól vagy már változott a dolog.
(#) Kokany82 hozzászólása Júl 4, 2016
Megmértem a jó ablakot és kb 3.5A felfelé 2.5-3 A lefelé,végálláshoz érve 11-12A. A rossz ablak 2. 6körül már megáll es csak kb egy perc múlva lépes normál sebességgel újra műkodni,fe szintén csak rövid ideig. Azt nem tudom,hogy a másik mikor megáll utana miért tud egyből elindulni újra,miért nem lell várni vele. Ezzel kapcsolatban fel tudna világosítani valaki?
(#) gordonfreemN válasza szepazelet hozzászólására (») Jún 21, 2016
Azt hiszem így nem szerencsés összekötni két tápegységet (lebeg) de talán egy teszt erejéig elmegy. 12V-on 12A-t tud a tápod ha jól számolom. Ha ez leesik 12V-ról 2-re az elég nagy baj.
Javaslatom, ne csak a lábkiosztásokat hanem az ellenállásokat is ellenőrizd le ujra. Az eredeti tervet vedd alapul ellenőrzéskor.
A hozzászólás módosítva: Jún 21, 2016
(#) kameleon2 válasza PIRO hozzászólására (») Jún 9, 2016
Szia! 32A-ig ingyen bővíthetsz. Azonban ha ennyire nem vagy tisztában ezzel a szakmával - inkább keres egy ismerős villanyszerelőt, mert nem elég távirányítással és bemondás alapján levezetékezni az épületet - legalábbis, ha nem szeretnél tüzet. Tanácsként: A merev, egyszeres szigetelésű vezeték - olcsóbb de sprődebb, nehezebben hajlik. A hajlékony egyszeres szigetelésű vezetékkel könnyebb dolgozni de drágább. Használhatsz sodrott kábelt is - az még jobb, könnyebben áttekinthető kábelezést ad, de jobban melegszik és még drágább. Azonban utóbbi tökéletesen alkalmas akár falon kívüli szerelésre is, vagy berendezés bekötésére. Használhatsz még MM-fal vezetéket és MBCu kábelt is ami szintén merev erű, de kettős szigeteléssel készül, valamint kör keresztmetszetű. Az MM-fal vezeték a gyors munkákhoz lett kitalálva - én személy szerint nem szeretem, mert ha egyszer be lett építve - lehetetlen vésés nélkül a cseréje. Ha csöveid vannak és jó minőségű a csövezés - elég lehet a legolcsóbb, egyszeres szigetelésű vezeték is. Fázisnak fekete, nullának kék, védővezetőnek zöldsárga szín kell. 16 - ig nagyjából elegendő az 1,5mm2-es, de erre inkább nézz meg pár méretezési táblázatot, mert terhelés és hosszfüggő a méret - vagy olvass vissza... A merev vezeték kötése egyszerűbb, a sodrotthoz már kell ez-az. végére például ajánlott az érvéghüvely és speciális kötőelemet érdemes hozzá inkább használni.
(#) Andralin hozzászólása Máj 30, 2016
Sziasztok!

Jó olvasgatni ezt a topikot és nézegetni mások mit építettek, gondoltam én is megosztom a nagy művemet, amin már több mint egy éve dolgozgatok és úgy néz ki ma lett véglegesen kész.

Van egy nyári tanya szerűség, ahol nincs fürdőszoba és vezetékes víz, csak egy hidrofóros fúrt kút és egy szabadban lévő hordós tusoló szerkezet. A hordóban egy 900 W-os törölközőszárító fűtőpatron van beszerelve, ez melegíti a vizet. Éveken keresztül a "hőfokszabályzást" a fűtőpatron konnektorba történő ki- bedugásával oldottuk meg, a vizfeltöltést pedig a kútra kötött, a hordóba vezetett slaggal manuálisan, a vízszintet egy nivőcsőként használt benzincsövön néztük, ami gyakran levízkövesedett és ilyenkor csak találgattunk mekkora lehet a vízszint. Emiatt gyakran kevesebb volt a víz, mint gondoltuk, így nem mindig jutott meleg víz mindenkinek a tusolásra, illetve több alkalommal is sikerült leégetni a fűtőpatront mert túl alacsony vízszint mellett lett bekapcsolva.

Ezeket a gondokat untam meg és szántam el magam tavaly tavasszal az egész rendszer automatizálására életem első ATMEL kontrolleres projectjével.

Az kész rendszer legfőbb jellemzői:

- ATMega 32A vezérlő
- fűtőpatron automatikus kapcsolgatása, DS18B20 hőmérsékletszenzor méri a víz hőfokát, a vezérlő a beállított hőfokig melegíti a vizet majd tartja azt
- fixen bekötött tömlő a hidroforról, vezérelt mágnesszeleppel, a feltöltés egy gombnyomással történik, a kívánt vízszint kiválasztható (Pl. 10%, 20%, 30%...)
- fűtőpatron védelem: alacsony vízszintnél letiltja a melegítést
- vízszint érzékelés ultrahangos távolságmérő szenzorral a hordó tetején lévő furatoknál, az aktuális vízszint pontos, százalékos kijelzése, figyelembe véve a távolság - körterület konverziót
- RTC belső óra, időzíthető fűtés ki- bekapcsolás, pl. reggeli zuhanyzáshoz beállított időben elkezdi a melegítést
- vízálló IP65-ös doboz, csatlakozók és nyomógombok
- nagy méretű 7 szegmenses LCD kijelzők (26 mm-es számmagasság) és LED háttérvilágítás a könnyű leolvashatóság kedvéért

Először a fotókon is látható próbapanelen raktam össze az egészet, utána csináltam meg a NYÁK-okat. A legnagyobb meló az összesen 96 darab LCD szegmens elvezetése volt, de sikerült megoldanom egyoldalas NYÁK-on. A végeredmény is látható a képeken.
(#) reloop válasza Massawa hozzászólására (») Máj 28, 2016
Mielőtt a lényegre térnék, végezzük ki a kapcsolóüzemű tápot!
Szemben a trafós tápokkal, ahol a maximális áramfelvétel effektív értékét kell tudni a forrásnak, a kapcsolóüzeműnél magát az áramcsúcsot is teljesítenie kell, mert különben leszabályoz.
A TDA2003 3,5A tartós és 4,5A nem ismétlődő csúcsot tud kezelni, ezért a három csatornás erősítőt illek legalább 12A-es kapcsitápról járatni.
A hangfrekvenciás erősítő megkövetelheti, hogy LC szűrőt iktassunk a kapcsolóüzemű táp után ahol a kondenzátorok alacsony ESR-je nagyon fontos.
Említetted, hogy 20000µF kondit raktál szűrőnek. Azzal az volt a baj, hogy a puffer-töltőáram elérte a táp áramkorlátját, és akár egyenetlenebb feszültséghez jutottál, mint annak előtte.
Most nézzük azt a szörnyű panelt, amit Rád sóztak. Ha ezt valaki a NYÁK-terv ellenőrzés témában mutatja be, komoly dorgálásra számíthat az unos unatalan leírt szabályok felrúgásáért.
Az A-C tápszakaszra rajzoltam egy nyilacskát. Na ott kéne abszolút veszteség mentesen akár 4A-nek is folyni. Nem fog, hanem tekintélyes feszültségesés jön létre és itt kezdődnek a bajok.
A visszacsatolás testre menő ellenállásán a D pontban megjelenik ez a vezetősáv-ellenálláson eső feszültség. A jeltestet akár A akár B pontra kötötted, a nyíllal jelölt sávon eső feszültség nem érinti. Az erősítő visszacsatolása nem tud mást tenni, mint igyekszik elnyomni a jeltest és a D pont közötti hibafeszültséget. Az erősítés mértéke miatt ez a gyakorlatban azt jelenti, 100mV kimeneti feszültség változás egyenlít ki 1mV hibát. Elnézve a fólia karcsúságát, a példában szereplő értékek nagyon alsó hangon közelítik meg a valós problémát.
Visszatérve a kapcsolóüzemű tápra, annak hullámossága is pont emiatt a súlyos NYÁK-tervezési hiba miatt kelt ekkora zavart.
Már a beszélgetésünk elején feltettem a gyártó ajánlását. Jól látható, ahogyan az IC 3-as láb alatt be van metszve a fólia, biztosítva a jel és a visszacsatolás föld szeparálását. Ezt bizony be kell tartani!
(#) zolee1209 hozzászólása Máj 19, 2016
Sziasztok!

Ge Lee és bistvan196700 nyomdokain teljes- hidas gép építésébe kezdtem. Az alkatrészek jobbára már megvannak, egy részük úton van. Alapvetően nincs szükségem nagy kimeneti áramra, mert most elsődlegesen csak 4mm-es zártszelvények hegesztése lenne a célom. Ugyanakkor rendelkezésemre áll egy fázison 32A és ehhez mérten szeretném majd elkészíteni a gépet kisebb túlméretezéssel. A kimeneti hegesztőáramot ~200A-ben maximalizálom, ami még függ a trafó áttételétől, a munkafeszültségeknek még utána kell olvasnom. És ami a kérdést illeti. Szándékomban áll egy kissé "multifunkcióssá" tenni a gépet, elsődlegesen ponthegesztőként. Ezt a vezérlés adott idejű tiltásával és engedélyezésével képzeltem el. Amennyiben a maximális üzemi áram kevés, de a transzformátorom engedi, tennék rá egy egymenetes tekercset, ami nem kapna egyenirányítást és fojtót. Itt a topikban olvastam valamerre, hogy fojtó nélkül üzemeltetve a hegesztőt megbolondulhat a vezérlés, ami a gép halálához vezethet. Ugyanez megtörténhet, ha a szekunder tekercsre nincs kötve semmi, csak a "terhelés"? Az árammódú szabályzás miatt úgy gondolom, hogy nem, viszont a kapcsolóüzemű áramkörökben nincs túl sok tapasztalatom, így szívesen fogadnám a hozzáértők véleményét.
(#) dani9228 válasza dani9228 hozzászólására (») Máj 14, 2016
Találtam vezetékeket. 0,35 és 0,25mm -eseket. Skori féle kalkulátort használtam, és ezek az eredmények jöttek ki.
primer: B = 0,17T ; f = 55kHz ; U = 12V ; Imax = 12A
N = 3 ( biffilárisan 6 menet ) ; párhuzamosított szálak száma = 31db
szek.: Imax = 4A ; U = 30V
N = 8 ( biffilárisan 16 menet ) ; párhozamosított szálak száma = 10db
Veszteségek miatt gondolom több kell a szekunderre.
A hozzászólás módosítva: Máj 14, 2016
(#) reloop válasza erik001 hozzászólására (») Máj 7, 2016
Feltéve, de meg nem engedve, mindkét csatorna zárlatos lesz. A 2x24VAC melyet a Graetz egyenirányít 4Ω eredő ellenálláson folyat áramot. Ez nagyjából 12A és a biztosíték kiolvadásáig azért folyhat éppen.
(#) pittyu2 válasza zsolt58 hozzászólására (») Máj 6, 2016
Itt csak a pénztárca vastagsága a határ.
Az is fontos kérdés mire akarod használni a "forgószárnyasodat ".
--Ipari méret filmforgatás megélhetési pénzkereset.
--Videózás saját kedvtelés,lakókörnyezet -utazgatás alkalmából felvételek.
-- Pörgés , forgás, rohangálás réten vagy fás-ligetes ,erdős ( esetleg FPV szemüveges )repülés.
Az én összeállításom :2db 250 méret FPV quad, NAZE 32 10 dof vezérlő-2205 motor 12A ESC.
1db NAZA V2 -gps -2826 motor -OSD -450 méret.
1 db Naza V2 -gps -4005 motor-OSD _gimbal 650 méret. Ez most át lesz építve hexa elrendezésre mert stabilmegbízhatóbb elrendezést akarok.
A NAZA vezérlők ára elég húzós , de meg vannak az előnyei :Kevés beállítással baromi nyugis repülés és ami neked is fontos - ha kell fail safe módban hazamegy a kiindulási pontra.
Van vezérlő ami precizebb , de annak a " finomhangolása" nagy szaktudást és időt kíván.
(#) Kera_Will válasza atus1981 hozzászólására (») Máj 2, 2016
Idézet:
„Ezek kiválthatóak ezzel az IC-vel és 300Ohm-os tekercsű relékkel?”

Mekkora feszültségű a relé?Azt oszd el 300 ohmmal.
Ha ez meg van akkor ennyi az 1 tranzisztoron átfolyó áram.
Összesen hány relét kapcsolsz?
Ezek az áramok összeadódnak és a feszültséggel megszorozva megkapod a maximális teljesítményt ha minden relé meg van húzva.
Ezt az össz teljesítmény adatot össze kell hasonlítani az ULN adatlapján lévő Ptot max értékkel.Ha ennél kisebb akkor jó és bírni fogja ... ha több akkor egyszerre nem húzhat meg minden relé az áramkörben.
12V / 300 ohm = 0.04 A => P = U^2/R = 0.48W
8szor: 0.32A => Prelé max = 12V*0.32A =3,84W
Ez kissé sok az ULN-ek adatlapja 2,2W enged meg.
Persze kevesebb relé vagy nagyobb ohmos vagy kisebb meghúzó feszültségű esetén nincs gond.
A hozzászólás módosítva: Máj 2, 2016
(#) Bender hozzászólása Máj 1, 2016
Üdv

Egy ingatlan bővítése miatt a mérőhely a lakáson belülre került. 20A-es egyfázisú és egy kis falba süllyesztett fa szekrényben van és a szokásos tetőre szerelt vascsőre van kötve az oszlopról jövő légkábel. Ha szeretnék felszereltetni egy vezérelt mérőt is és 32A-re szeretném a mérőt bővíttetni, akkor a jelenlegi mérőhelyet vajon megtarthatom (nagyobbra cserélve, hogy beférjenek a plusz mérő és tartozékai) vagy akkor mindenképp a lakáson kívülre kell szereltetnem, hogy az ÉMÁSZ örüljön?

Ha át kell helyezni, akkor:
-A régi csatlakozási pont megmaradhat vagy át kell tenni a csövet a lehető legközelebb a mérőhöz?
-A műanyag mérődoboz sülyesztett kell, hogy legyen, vagy lehet felfelületre szerelt is? Eseteg elég ha csak félig-meddig van kivésve neki a fal?
-A légkábelt csak a tetőn kiálló csőbe lehet bevezetni, vagy esetleg egy falra szerelt horgonyra is rá lehet kötni, ahonnan egy védőcsőben mehet le a mérőig? Kb 280 cm magasan van a födém a talajszinthez viszonyítva.
Ha cső kell, akkor azt lehet a falra felületére is rögzíteni vagy annak is mindenképp végig kell vésni a falat?

Miért nem teszi a nyives mérőjét a szolgáltató egyből az oszlop tetejére. Max ad hozzá egy távcsövet, hogy le tudd olvasni meg egy botot, amivel felnyomod a megszakítót ha lekapcsolna.
(#) mineral hozzászólása Ápr 25, 2016
Sziasztok!

Családi házunk felső szintjének elektromos fogyasztását szeretném mérni. Találtam Sínre pattintható kivitelűt almérőt is. Ez lenne a legegyszerűbb. A Lakáselosztóban a bőven el is férne. Két kérdésem lenne felétek.
1. Ez esetben mit jelent az 5A-es áram? Ib?
Almérő
Használati utasítás
2. A fogyasztók között elektromos főzőlap és sütő is van. Igaz , hogy Imax 32A de tényleg bírja az ilyen nagy terheléseket?

Válaszokat köszönöm előre is.
A hozzászólás módosítva: Ápr 25, 2016
(#) pont válasza szamóca hozzászólására (») Ápr 21, 2016
Azt nem tudom van-e képlet vagy csak tapasztalatok alapján, de tény, hogy a gyári három mágneskapcsolós csillag delta egységben kisebb van ott. Bővebben: Link ha érdekel a pontos adat, akkor holnap nézek egyet. Persze lehet, hogy a SCHNEIDER ELECTRIC-nél sem értenek hozzá. Viszont tény, hogy régebben (30 éve) két DIL mágneskapcsolóval csináltuk és azok egyformák voltak...
A hozzászólás módosítva: Ápr 21, 2016
(#) Jossz hozzászólása Ápr 9, 2016
Sziasztok,
Kis segítségre lenne szükségem.
Programmal terveztem egy trafót több variációban, ebből már látható volt a szükséges ferritmag típusa és mérete. ****
A szükséges kiinduló paraméterek:

Mag: ETD 54/28/19 vagy ETD 59/31/22, anyag 3C90 vagy 3C94
Primer oldal: 24 VAC szinusz, a meghajtás 1,6 A-t bír el. A frekvencia 18 kHz.
Szekunder oldal: 16000 VAC (16 kVAC), 0,02A (20 mA)

Témához nem kapcsoló részt kivettem, arra ott az apróhirdetés!
ÜDV: Moderátor
A hozzászólás módosítva: Ápr 9, 2016
(#) Ge Lee válasza szikorapéter hozzászólására (») Ápr 6, 2016
Hogy a kapcsolóelemek fetek vagy tranyók voltak azt a kapcsolási elrendezésből ki lehet deríteni, meg a topológiát is ami szinte biztos hogy félhíd. Ha tranyók, akkor bármilyen 400V/6-12A-es jó bele teljesítmény függvényében.
De nem ok nélkül mentek tönkre, az új is tönkre fog menni ha beleteszed mielőtt kiderítenéd a hiba okát.
(#) eSDi válasza kadarist hozzászólására (») Márc 29, 2016
Nem lehet, hogy NTC? Ha már sorba van kötve a fűtőcsővel.
Mondjuk SCK-0212-vel (2Ohm és 12A, 20mm átmérő) megegyező, csak szegény zárlatos lett.
(#) eyess válasza kowi hozzászólására (») Márc 27, 2016
Pont ez a lényeg , ha már ilyen kis terhelésre is kikapcsol , akkor sosem fogja tudni a 42A es terhelést.
Tedd rá az izzót , de közbe legyen gy műszer a puffer kondenzátoron , hogy leesik e nagy mértékben a puffer feszültség. Itt most nem is az a lényeg , hogy teljes mértékben 42A es terhelés legyen , hisz már egy izzó terhelésre is leáll a táp , és az pedig nem vesz fel 42A ert.
(#) kowi válasza eyess hozzászólására (») Márc 27, 2016
Az a baj hogy esély sincs mérni mivel ez egy 42A-os táp és egy 21w-os izzónál is kikapcsol...
(#) torci hozzászólása Márc 24, 2016
Sziasztok!
HFA15TB60 diodak helyett DSEP12-12A jelzésű diódákat tudnék szerezni. Az adatlapokat összehasonlítva jónak tűnik helyette. Jól gondolom, vagy tévedek? A többi alkatrészt úgy tünik sikerül beszerezni.
Köszönöm mindenkinek a segítséget....
(#) kapu48 válasza szikorapéter hozzászólására (») Márc 23, 2016
Itt van ahogy én csináltam:
  1. ////////////////////////////////////////////////////////////////////////////////
  2. // TinyBasic Plus
  3. ////////////////////////////////////////////////////////////////////////////////
  4. //
  5. // Authors: Mike Field <hamster@snap.net.nz>
  6. //          Scott Lawrence <yorgle@gmail.com>
  7. //
  8. #include "SPI.h"
  9. #include "Adafruit_GFX.h"
  10. #include "Adafruit_ILI9340.h"
  11.  
  12. #if defined(__SAM3X8E__)
  13.     #undef __FlashStringHelper::F(string_literal)
  14.     #define F(string_literal) string_literal
  15. #endif
  16.  
  17. // These are the pins used for the UNO
  18. // for Due/Mega/Leonardo use the hardware SPI pins (which are different)
  19. #define _sclk 13
  20. #define _miso 12
  21. #define _mosi 11
  22. #define _cs 10
  23. #define _dc 9
  24. #define _rst 8
  25.  
  26. // Using software SPI is really not suggested, its incredibly slow
  27. //Adafruit_ILI9340 tft = Adafruit_ILI9340(_cs, _dc, _mosi, _sclk, _rst, _miso);
  28. // Use hardware SPI
  29. Adafruit_ILI9340 tft = Adafruit_ILI9340(_cs, _dc, _rst);
  30.  
  31. #define kVersion "v0.13"
  32.  
  33. // v0.13: 2013-03-04
  34. //      Support for Arduino 1.5 (SPI.h included, additional changes for DUE support)
  35. //
  36. // v0.12: 2013-03-01
  37. //      EEPROM load and save routines added: EFORMAT, ELIST, ELOAD, ESAVE, ECHAIN
  38. //      added EAUTORUN option (chains to EEProm saved program on startup)
  39. //      Bugfixes to build properly on non-arduino systems (PROGMEM #define workaround)
  40. //      cleaned up a bit of the #define options wrt TONE
  41. //
  42. // v0.11: 2013-02-20
  43. //      all display strings and tables moved to PROGMEM to save space
  44. //      removed second serial
  45. //      removed pinMode completely, autoconf is explicit
  46. //      beginnings of EEPROM related functionality (new,load,save,list)
  47. //
  48. // v0.10: 2012-10-15
  49. //      added kAutoConf, which eliminates the "PINMODE" statement.
  50. //      now, DWRITE,DREAD,AWRITE,AREAD automatically set the PINMODE appropriately themselves.
  51. //      should save a few bytes in your programs.
  52. //
  53. // v0.09: 2012-10-12
  54. //      Fixed directory listings.  FILES now always works. (bug in the SD library)
  55. //      fixed filesize printouts (added printUnum for unsigned numbers)
  56. //      #defineable baud rate for slow connection throttling
  57. //e
  58. // v0.08: 2012-10-02
  59. //      Tone generation through piezo added (TONE, TONEW, NOTONE)
  60. //
  61. // v0.07: 2012-09-30
  62. //      Autorun buildtime configuration feature
  63. //
  64. // v0.06: 2012-09-27
  65. //      Added optional second serial input, used for an external keyboard
  66. //
  67. // v0.05: 2012-09-21
  68. //      CHAIN to load and run a second file
  69. //      RND,RSEED for random stuff
  70. //      Added "!=" for "<>" synonym
  71. //      Added "END" for "STOP" synonym (proper name for the functionality anyway)
  72. //
  73. // v0.04: 2012-09-20
  74. //      DELAY ms   - for delaying
  75. //      PINMODE <pin>, INPUT|IN|I|OUTPUT|OUT|O
  76. //      DWRITE <pin>, HIGH|HI|1|LOW|LO|0
  77. //      AWRITE <pin>, [0..255]
  78. //      fixed "save" appending to existing files instead of overwriting
  79. //      Updated for building desktop command line app (incomplete)
  80. //
  81. // v0.03: 2012-09-19
  82. //      Integrated Jurg Wullschleger whitespace,unary fix
  83. //      Now available through github
  84. //      Project renamed  "Tiny Basic in C" to "TinyBasic Plus"
  85. //         
  86. // v0.02b: 2012-09-17  Scott Lawrence <yorgle@gmail.com>
  87. //      Better FILES listings
  88. //
  89. // v0.02a: 2012-09-17  Scott Lawrence <yorgle@gmail.com>
  90. //      Support for SD Library
  91. //      Added: SAVE, FILES (mostly works), LOAD (mostly works) (redirects IO)
  92. //      Added: MEM, ? (PRINT)
  93. //      Quirk:  "10 LET A=B+C" is ok "10 LET A = B + C" is not.
  94. //      Quirk:  INPUT seems broken?
  95.  
  96.  
  97.  
  98. // IF testing with Visual C, this needs to be the first thing in the file.
  99. //#include "stdafx.h"
  100.  
  101.  
  102. char eliminateCompileErrors = 1;  // fix to suppress arduino build errors
  103.  
  104. // hack to let makefiles work with this file unchanged
  105. #ifdef FORCE_DESKTOP
  106. #undef ARDUINO
  107. #else
  108. #define ARDUINO 1
  109. #endif
  110.  
  111.  
  112. ////////////////////////////////////////////////////////////////////////////////
  113. // Feature option configuration...
  114.  
  115. // This enables LOAD, SAVE, FILES commands through the Arduino SD Library
  116. // it adds 9k of usage as well.
  117. //#define ENABLE_FILEIO 1
  118. #undef ENABLE_FILEIO
  119.  
  120. // this turns on "autorun".  if there's FileIO, and a file "autorun.bas",
  121. // then it will load it and run it when starting up
  122. //#define ENABLE_AUTORUN 1
  123. #undef ENABLE_AUTORUN
  124. // and this is the file that gets run
  125. #define kAutorunFilename  "autorun.bas"
  126.  
  127. // this is the alternate autorun.  Autorun the program in the eeprom.
  128. // it will load whatever is in the EEProm and run it
  129. #define ENABLE_EAUTORUN 1
  130. //#undef ENABLE_EAUTORUN
  131.  
  132. // this will enable the "TONE", "NOTONE" command using a piezo
  133. // element on the specified pin.  Wire the red/positive/piezo to the kPiezoPin,
  134. // and the black/negative/metal disc to ground.
  135. // it adds 1.5k of usage as well.
  136. //#define ENABLE_TONES 1
  137. #undef ENABLE_TONES
  138. #define kPiezoPin 5
  139.  
  140. // we can use the EEProm to store a program during powerdown.  This is
  141. // 1kbyte on the '328, and 512 bytes on the '168.  Enabling this here will
  142. // allow for this funcitonality to work.  Note that this only works on AVR
  143. // arduino.  Disable it for DUE/other devices.
  144. #define ENABLE_EEPROM 1
  145. //#undef ENABLE_EEPROM
  146.  
  147. // Sometimes, we connect with a slower device as the console.
  148. // Set your console D0/D1 baud rate here (9600 baud default)
  149. #define kConsoleBaud 9600
  150.  
  151. ////////////////////////////////////////////////////////////////////////////////
  152. #ifdef ARDUINO
  153. #ifndef RAMEND
  154. // okay, this is a hack for now
  155. // if we're in here, we're a DUE probably (ARM instead of AVR)
  156.  
  157. #define RAMEND 4096-1
  158.  
  159. // turn off EEProm
  160. #undef ENABLE_EEPROM
  161. #undef ENABLE_TONES
  162.  
  163. #else
  164. // we're an AVR!
  165.  
  166. // we're moving our data strings into progmem
  167. #include <avr/pgmspace.h>
  168. #endif
  169.  
  170. // includes, and settings for Arduino-specific functionality
  171. #ifdef ENABLE_EEPROM
  172. #include <EEPROM.h>  /* NOTE: case sensitive */
  173. int eepos = 0;
  174. #endif
  175.  
  176.  
  177. #ifdef ENABLE_FILEIO
  178. #include <SD.h>
  179. #include <SPI.h> /* needed as of 1.5 beta */
  180.  
  181. // Arduino-specific configuration
  182. // set this to the card  for your SD shield
  183. #define kSD_CS 10
  184.  
  185. #define kSD_Fail  0
  186. #define kSD_OK    1
  187.  
  188. File fp;
  189. #endif
  190.  
  191. // set up our RAM buffer size for program and user input
  192. // NOTE: This number will have to change if you include other libraries.
  193. #ifdef ARDUINO
  194. #ifdef ENABLE_FILEIO
  195. #define kRamFileIO (1030) /* approximate */
  196. #else
  197. #define kRamFileIO (0)
  198. #endif
  199. #ifdef ENABLE_TONES
  200. #define kRamTones (40)
  201. #else
  202. #define kRamTones (0)
  203. #endif
  204. #endif /* ARDUINO */
  205. #define kRamSize  (RAMEND - 1160 - kRamFileIO - kRamTones)
  206.  
  207. #ifndef ARDUINO
  208. // Not arduino setup
  209. #include <stdio.h>
  210. #include <stdlib.h>
  211. #undef ENABLE_TONES
  212.  
  213. // size of our program ram
  214. #define kRamSize   4096 /* arbitrary */
  215.  
  216. #ifdef ENABLE_FILEIO
  217. FILE * fp;
  218. #endif
  219. #endif
  220.  
  221. #ifdef ENABLE_FILEIO
  222. // functions defined elsehwere
  223. void cmd_Files( void );
  224. #endif
  225.  
  226. ////////////////////
  227.  
  228. #ifndef boolean
  229. #define boolean int
  230. #define true 1
  231. #define false 0
  232. #endif
  233. #endif
  234.  
  235. #ifndef byte
  236. typedef unsigned char byte;
  237. #endif
  238.  
  239. // some catches for AVR based text string stuff...
  240. #ifndef PROGMEM
  241. #define PROGMEM
  242. #endif
  243. #ifndef pgm_read_byte
  244. #define pgm_read_byte( A ) *(A)
  245. #endif
  246.  
  247. ////////////////////
  248.  
  249. #ifdef ENABLE_FILEIO
  250. unsigned char * filenameWord(void);
  251. static boolean sd_is_initialized = false;
  252. #endif
  253.  
  254. boolean inhibitOutput = false;
  255. static boolean runAfterLoad = false;
  256. static boolean triggerRun = false;
  257.  
  258. // these will , at runtime, where IO happens through for load/save
  259. enum {
  260.   kStreamSerial = 0,
  261.   kStreamEEProm,
  262.   kStreamFile
  263. };
  264. static unsigned char inStream = kStreamSerial;
  265. static unsigned char outStream = kStreamSerial;
  266.  
  267.  
  268. ////////////////////////////////////////////////////////////////////////////////
  269. // ASCII Characters
  270. #define CR      '\r'
  271. #define NL      '\n'
  272. #define LF      0x0a
  273. #define TAB     '\t'
  274. #define BELL    '\b'
  275. #define SPACE   ' '
  276. #define SQUOTE  '\''
  277. #define DQUOTE  '\"'
  278. #define CTRLC   0x03
  279. #define CTRLH   0x08
  280. #define CTRLS   0x13
  281. #define CTRLX   0x18
  282.  
  283. typedef short unsigned LINENUM;
  284. #ifdef ARDUINO
  285. #define ECHO_CHARS 1
  286. #else
  287. #define ECHO_CHARS 0
  288. #endif
  289.  
  290.  
  291. static unsigned char program[kRamSize];
  292. static const char *  sentinel = "HELLO";
  293. static unsigned char *txtpos,*list_line;
  294. static unsigned char expression_error;
  295. static unsigned char *tempsp;
  296.  
  297. /***********************************************************/
  298. // Keyword table and constants - the last character has 0x80 added to it
  299. static const unsigned char keywords[] PROGMEM = {
  300.   'L','I','S','T'+0x80,
  301.   'L','O','A','D'+0x80,
  302.   'N','E','W'+0x80,
  303.   'R','U','N'+0x80,
  304.   'S','A','V','E'+0x80,
  305.   'N','E','X','T'+0x80,
  306.   'L','E','T'+0x80,
  307.   'I','F'+0x80,
  308.   'G','O','T','O'+0x80,
  309.   'G','O','S','U','B'+0x80,
  310.   'R','E','T','U','R','N'+0x80,
  311.   'R','E','M'+0x80,
  312.   'F','O','R'+0x80,
  313.   'I','N','P','U','T'+0x80,
  314.   'P','R','I','N','T'+0x80,
  315.   'P','O','K','E'+0x80,
  316.   'S','T','O','P'+0x80,
  317.   'B','Y','E'+0x80,
  318.   'F','I','L','E','S'+0x80,
  319.   'M','E','M'+0x80,
  320.   '?'+ 0x80,
  321.   '\''+ 0x80,
  322.   'A','W','R','I','T','E'+0x80,
  323.   'D','W','R','I','T','E'+0x80,
  324.   'D','E','L','A','Y'+0x80,
  325.   'E','N','D'+0x80,
  326.   'R','S','E','E','D'+0x80,
  327.   'C','H','A','I','N'+0x80,
  328. #ifdef ENABLE_TONES
  329.   'T','O','N','E','W'+0x80,
  330.   'T','O','N','E'+0x80,
  331.   'N','O','T','O','N','E'+0x80,
  332. #endif
  333. #ifdef ARDUINO
  334. #ifdef ENABLE_EEPROM
  335.   'E','C','H','A','I','N'+0x80,
  336.   'E','L','I','S','T'+0x80,
  337.   'E','L','O','A','D'+0x80,
  338.   'E','F','O','R','M','A','T'+0x80,
  339.   'E','S','A','V','E'+0x80,
  340. #endif
  341. #endif
  342.   0
  343. };
  344.  
  345. // by moving the command list to an enum, we can easily remove sections
  346. // above and below simultaneously to ively obliterate functionality.
  347. enum {
  348.   KW_LIST = 0,
  349.   KW_LOAD, KW_NEW, KW_RUN, KW_SAVE,
  350.   KW_NEXT, KW_LET, KW_IF,
  351.   KW_GOTO, KW_GOSUB, KW_RETURN,
  352.   KW_REM,
  353.   KW_FOR,
  354.   KW_INPUT, KW_PRINT,
  355.   KW_POKE,
  356.   KW_STOP, KW_BYE,
  357.   KW_FILES,
  358.   KW_MEM,
  359.   KW_QMARK, KW_QUOTE,
  360.   KW_AWRITE, KW_DWRITE,
  361.   KW_DELAY,
  362.   KW_END,
  363.   KW_RSEED,
  364.   KW_CHAIN,
  365. #ifdef ENABLE_TONES
  366.   KW_TONEW, KW_TONE, KW_NOTONE,
  367. #endif
  368. #ifdef ARDUINO
  369. #ifdef ENABLE_EEPROM
  370.   KW_ECHAIN, KW_ELIST, KW_ELOAD, KW_EFORMAT, KW_ESAVE,
  371. #endif
  372. #endif
  373.   KW_DEFAULT /* always the final one*/
  374. };
  375.  
  376. struct stack_for_frame {
  377.   char frame_type;
  378.   char for_var;
  379.   short int terminal;
  380.   short int step;
  381.   unsigned char *current_line;
  382.   unsigned char *txtpos;
  383. };
  384.  
  385. struct stack_gosub_frame {
  386.   char frame_type;
  387.   unsigned char *current_line;
  388.   unsigned char *txtpos;
  389. };
  390.  
  391. static const unsigned char func_tab[] PROGMEM = {
  392.   'P','E','E','K'+0x80,
  393.   'A','B','S'+0x80,
  394.   'A','R','E','A','D'+0x80,
  395.   'D','R','E','A','D'+0x80,
  396.   'R','N','D'+0x80,
  397.   0
  398. };
  399. #define FUNC_PEEK    0
  400. #define FUNC_ABS     1
  401. #define FUNC_AREAD   2
  402. #define FUNC_DREAD   3
  403. #define FUNC_RND     4
  404. #define FUNC_UNKNOWN 5
  405.  
  406. static const unsigned char to_tab[] PROGMEM = {
  407.   'T','O'+0x80,
  408.   0
  409. };
  410.  
  411. static const unsigned char step_tab[] PROGMEM = {
  412.   'S','T','E','P'+0x80,
  413.   0
  414. };
  415.  
  416. static const unsigned char relop_tab[] PROGMEM = {
  417.   '>','='+0x80,
  418.   '<','>'+0x80,
  419.   '>'+0x80,
  420.   '='+0x80,
  421.   '<','='+0x80,
  422.   '<'+0x80,
  423.   '!','='+0x80,
  424.   0
  425. };
  426.  
  427. #define RELOP_GE                0
  428. #define RELOP_NE                1
  429. #define RELOP_GT                2
  430. #define RELOP_EQ                3
  431. #define RELOP_LE                4
  432. #define RELOP_LT                5
  433. #define RELOP_NE_BANG           6
  434. #define RELOP_UNKNOWN   7
  435.  
  436. static const unsigned char highlow_tab[] PROGMEM = {
  437.   'H','I','G','H'+0x80,
  438.   'H','I'+0x80,
  439.   'L','O','W'+0x80,
  440.   'L','O'+0x80,
  441.   0
  442. };
  443. #define HIGHLOW_HIGH    1
  444. #define HIGHLOW_UNKNOWN 4
  445.  
  446. #define STACK_SIZE (sizeof(struct stack_for_frame)*5)
  447. #define VAR_SIZE sizeof(short int) // Size of variables in bytes
  448.  
  449. static unsigned char *stack_limit;
  450. static unsigned char *program_start;
  451. static unsigned char *program_end;
  452. static unsigned char *stack; // Software stack for things that should go on the CPU stack
  453. static unsigned char *variables_begin;
  454. static unsigned char *current_line;
  455. static unsigned char *sp;
  456. #define STACK_GOSUB_FLAG 'G'
  457. #define STACK_FOR_FLAG 'F'
  458. static unsigned char table_index;
  459. static LINENUM linenum;
  460.  
  461. static const unsigned char okmsg[]            PROGMEM = "OK";
  462. static const unsigned char whatmsg[]          PROGMEM = "What? ";
  463. static const unsigned char howmsg[]           PROGMEM = "How?";
  464. static const unsigned char sorrymsg[]         PROGMEM = "Sorry!";
  465. static const unsigned char initmsg[]          PROGMEM = "TinyBasic Plus " kVersion;
  466. static const unsigned char memorymsg[]        PROGMEM = " bytes free.";
  467. #ifdef ARDUINO
  468. #ifdef ENABLE_EEPROM
  469. static const unsigned char eeprommsg[]        PROGMEM = " EEProm bytes total.";
  470. static const unsigned char eepromamsg[]       PROGMEM = " EEProm bytes available.";
  471. #endif
  472. #endif
  473. static const unsigned char breakmsg[]         PROGMEM = "break!";
  474. static const unsigned char unimplimentedmsg[] PROGMEM = "Unimplemented";
  475. static const unsigned char backspacemsg[]     PROGMEM = "\b \b";
  476. static const unsigned char indentmsg[]        PROGMEM = "    ";
  477. static const unsigned char sderrormsg[]       PROGMEM = "SD card error.";
  478. static const unsigned char sdfilemsg[]        PROGMEM = "SD file error.";
  479. static const unsigned char dirextmsg[]        PROGMEM = "(dir)";
  480. static const unsigned char slashmsg[]         PROGMEM = "/";
  481. static const unsigned char spacemsg[]         PROGMEM = " ";
  482.  
  483. static int inchar(void);
  484. static void outchar(unsigned char c);
  485. static void line_terminator(void);
  486. static short int expression(void);
  487. static unsigned char breakcheck(void);
  488. /***************************************************************************/
  489. static void ignore_blanks(void)
  490. {
  491.   while(*txtpos == SPACE || *txtpos == TAB)
  492.     txtpos++;
  493. }
  494.  
  495.  
  496. /***************************************************************************/
  497. static void scantable(const unsigned char *table)
  498. {
  499.   int i = 0;
  500.   table_index = 0;
  501.   while(1)
  502.   {
  503.     // Run out of table entries?
  504.     if(pgm_read_byte( table ) == 0)
  505.       return;
  506.  
  507.     // Do we match this character?
  508.     if(txtpos[i] == pgm_read_byte( table ))
  509.     {
  510.       i++;
  511.       table++;
  512.     }
  513.     else
  514.     {
  515.       // do we match the last character of keywork (with 0x80 added)? If so, return
  516.       if(txtpos[i]+0x80 == pgm_read_byte( table ))
  517.       {
  518.         txtpos += i+1;  // Advance the pointer to following the keyword
  519.         ignore_blanks();
  520.         return;
  521.       }
  522.  
  523.       // Forward to the end of this keyword
  524.       while((pgm_read_byte( table ) & 0x80) == 0)
  525.         table++;
  526.  
  527.       // Now move on to the first character of the next word, and reset the position index
  528.       table++;
  529.       table_index++;
  530.       ignore_blanks();
  531.       i = 0;
  532.     }
  533.   }
  534. }
  535.  
  536. /***************************************************************************/
  537. static void pushb(unsigned char b)
  538. {
  539.   sp--;
  540.   *sp = b;
  541. }
  542.  
  543. /***************************************************************************/
  544. static unsigned char popb()
  545. {
  546.   unsigned char b;
  547.   b = *sp;
  548.   sp++;
  549.   return b;
  550. }
  551.  
  552. /***************************************************************************/
  553. void printnum(int num)
  554. {
  555.   int digits = 0;
  556.  
  557.   if(num < 0)
  558.   {
  559.     num = -num;
  560.     outchar('-');
  561.   }
  562.   do {
  563.     pushb(num%10+'0');
  564.     num = num/10;
  565.     digits++;
  566.   }
  567.   while (num > 0);
  568.  
  569.   while(digits > 0)
  570.   {
  571.     outchar(popb());
  572.     digits--;
  573.   }
  574. }
  575.  
  576. void printUnum(unsigned int num)
  577. {
  578.   int digits = 0;
  579.  
  580.   do {
  581.     pushb(num%10+'0');
  582.     num = num/10;
  583.     digits++;
  584.   }
  585.   while (num > 0);
  586.  
  587.   while(digits > 0)
  588.   {
  589.     outchar(popb());
  590.     digits--;
  591.   }
  592. }
  593.  
  594. /***************************************************************************/
  595. static unsigned short testnum(void)
  596. {
  597.   unsigned short num = 0;
  598.   ignore_blanks();
  599.  
  600.   while(*txtpos>= '0' && *txtpos <= '9' )
  601.   {
  602.     // Trap overflows
  603.     if(num >= 0xFFFF/10)
  604.     {
  605.       num = 0xFFFF;
  606.       break;
  607.     }
  608.  
  609.     num = num *10 + *txtpos - '0';
  610.     txtpos++;
  611.   }
  612.   return        num;
  613. }
  614.  
  615. /***************************************************************************/
  616. static unsigned char print_quoted_string(void)
  617. {
  618.   int i=0;
  619.   unsigned char delim = *txtpos;
  620.   if(delim != '"' && delim != '\'')
  621.     return 0;
  622.   txtpos++;
  623.  
  624.   // Check we have a closing delimiter
  625.   while(txtpos[i] != delim)
  626.   {
  627.     if(txtpos[i] == NL)
  628.       return 0;
  629.     i++;
  630.   }
  631.  
  632.   // Print the characters
  633.   while(*txtpos != delim)
  634.   {
  635.     outchar(*txtpos);
  636.     txtpos++;
  637.   }
  638.   txtpos++; // Skip over the last delimiter
  639.  
  640.   return 1;
  641. }
  642.  
  643.  
  644. /***************************************************************************/
  645. void printmsgNoNL(const unsigned char *msg)
  646. {
  647.   while( pgm_read_byte( msg ) != 0 ) {
  648.     outchar( pgm_read_byte( msg++ ) );
  649.   };
  650. }
  651.  
  652. /***************************************************************************/
  653. void printmsg(const unsigned char *msg)
  654. {
  655.   printmsgNoNL(msg);
  656.   line_terminator();
  657. }
  658.  
  659. /***************************************************************************/
  660. static void getln(char prompt)
  661. {
  662.   outchar(prompt);
  663.   txtpos = program_end+sizeof(LINENUM);
  664.  
  665.   while(1)
  666.   {
  667.     char c = inchar();
  668.     switch(c)
  669.     {
  670.     case NL:
  671.       //break;
  672.     case CR:
  673.       line_terminator();
  674.       // Terminate all strings with a NL
  675.       txtpos[0] = NL;
  676.       return;
  677.     case CTRLH:
  678.       if(txtpos == program_end)
  679.         break;
  680.       txtpos--;
  681.  
  682.       printmsg(backspacemsg);
  683.       break;
  684.     default:
  685.       // We need to leave at least one space to allow us to shuffle the line into order
  686.       if(txtpos == variables_begin-2)
  687.         outchar(BELL);
  688.       else
  689.       {
  690.         txtpos[0] = c;
  691.         txtpos++;
  692.         outchar(c);
  693.       }
  694.     }
  695.   }
  696. }
  697.  
  698. /***************************************************************************/
  699. static unsigned char *findline(void)
  700. {
  701.   unsigned char *line = program_start;
  702.   while(1)
  703.   {
  704.     if(line == program_end)
  705.       return line;
  706.  
  707.     if(((LINENUM *)line)[0] >= linenum)
  708.       return line;
  709.  
  710.     // Add the line length onto the current address, to get to the next line;
  711.     line += line[sizeof(LINENUM)];
  712.   }
  713. }
  714.  
  715. /***************************************************************************/
  716. static void toUppercaseBuffer(void)
  717. {
  718.   unsigned char *c = program_end+sizeof(LINENUM);
  719.   unsigned char quote = 0;
  720.  
  721.   while(*c != NL)
  722.   {
  723.     // Are we in a quoted string?
  724.     if(*c == quote)
  725.       quote = 0;
  726.     else if(*c == '"' || *c == '\'')
  727.       quote = *c;
  728.     else if(quote == 0 && *c >= 'a' && *c <= 'z')
  729.       *c = *c + 'A' - 'a';
  730.     c++;
  731.   }
  732. }
  733.  
  734. /***************************************************************************/
  735. void printline()
  736. {
  737.   LINENUM line_num;
  738.  
  739.   line_num = *((LINENUM *)(list_line));
  740.   list_line += sizeof(LINENUM) + sizeof(char);
  741.  
  742.   // Output the line */
  743.   printnum(line_num);
  744.   outchar(' ');
  745.   while(*list_line != NL)
  746.   {
  747.     outchar(*list_line);
  748.     list_line++;
  749.   }
  750.   list_line++;
  751.   line_terminator();
  752. }
  753.  
  754. /***************************************************************************/
  755. static short int expr4(void)
  756. {
  757.   // fix provided by Jurg Wullschleger wullschleger@gmail.com
  758.   // fixes whitespace and unary operations
  759.   ignore_blanks();
  760.  
  761.   if( *txtpos == '-' ) {
  762.     txtpos++;
  763.     return -expr4();
  764.   }
  765.   // end fix
  766.  
  767.   if(*txtpos == '0')
  768.   {
  769.     txtpos++;
  770.     return 0;
  771.   }
  772.  
  773.   if(*txtpos >= '1' && *txtpos <= '9')
  774.   {
  775.     short int a = 0;
  776.     do  {
  777.       a = a*10 + *txtpos - '0';
  778.       txtpos++;
  779.     }
  780.     while(*txtpos >= '0' && *txtpos <= '9');
  781.     return a;
  782.   }
  783.  
  784.   // Is it a function or variable reference?
  785.   if(txtpos[0] >= 'A' && txtpos[0] <= 'Z')
  786.   {
  787.     short int a;
  788.     // Is it a variable reference (single alpha)
  789.     if(txtpos[1] < 'A' || txtpos[1] > 'Z')
  790.     {
  791.       a = ((short int *)variables_begin)[*txtpos - 'A'];
  792.       txtpos++;
  793.       return a;
  794.     }
  795.  
  796.     // Is it a function with a single parameter
  797.     scantable(func_tab);
  798.     if(table_index == FUNC_UNKNOWN)
  799.       goto expr4_error;
  800.  
  801.     unsigned char f = table_index;
  802.  
  803.     if(*txtpos != '(')
  804.       goto expr4_error;
  805.  
  806.     txtpos++;
  807.     a = expression();
  808.     if(*txtpos != ')')
  809.       goto expr4_error;
  810.     txtpos++;
  811.     switch(f)
  812.     {
  813.     case FUNC_PEEK:
  814.       return program[a];
  815.      
  816.     case FUNC_ABS:
  817.       if(a < 0)
  818.         return -a;
  819.       return a;
  820.  
  821. #ifdef ARDUINO
  822.     case FUNC_AREAD:
  823.       pinMode( a, INPUT );
  824.       return analogRead( a );                        
  825.     case FUNC_DREAD:
  826.       pinMode( a, INPUT );
  827.       return digitalRead( a );
  828. #endif
  829.  
  830.     case FUNC_RND:
  831. #ifdef ARDUINO
  832.       return( random( a ));
  833. #else
  834.       return( rand() % a );
  835. #endif
  836.     }
  837.   }
  838.  
  839.   if(*txtpos == '(')
  840.   {
  841.     short int a;
  842.     txtpos++;
  843.     a = expression();
  844.     if(*txtpos != ')')
  845.       goto expr4_error;
  846.  
  847.     txtpos++;
  848.     return a;
  849.   }
  850.  
  851. expr4_error:
  852.   expression_error = 1;
  853.   return 0;
  854.  
  855. }
  856.  
  857. /***************************************************************************/
  858. static short int expr3(void)
  859. {
  860.   short int a,b;
  861.  
  862.   a = expr4();
  863.  
  864.   ignore_blanks(); // fix for eg:  100 a = a + 1
  865.  
  866.   while(1)
  867.   {
  868.     if(*txtpos == '*')
  869.     {
  870.       txtpos++;
  871.       b = expr4();
  872.       a *= b;
  873.     }
  874.     else if(*txtpos == '/')
  875.     {
  876.       txtpos++;
  877.       b = expr4();
  878.       if(b != 0)
  879.         a /= b;
  880.       else
  881.         expression_error = 1;
  882.     }
  883.     else
  884.       return a;
  885.   }
  886. }
  887.  
  888. /***************************************************************************/
  889. static short int expr2(void)
  890. {
  891.   short int a,b;
  892.  
  893.   if(*txtpos == '-' || *txtpos == '+')
  894.     a = 0;
  895.   else
  896.     a = expr3();
  897.  
  898.   while(1)
  899.   {
  900.     if(*txtpos == '-')
  901.     {
  902.       txtpos++;
  903.       b = expr3();
  904.       a -= b;
  905.     }
  906.     else if(*txtpos == '+')
  907.     {
  908.       txtpos++;
  909.       b = expr3();
  910.       a += b;
  911.     }
  912.     else
  913.       return a;
  914.   }
  915. }
  916. /***************************************************************************/
  917. static short int expression(void)
  918. {
  919.   short int a,b;
  920.  
  921.   a = expr2();
  922.  
  923.   // Check if we have an error
  924.   if(expression_error)  return a;
  925.  
  926.   scantable(relop_tab);
  927.   if(table_index == RELOP_UNKNOWN)
  928.     return a;
  929.  
  930.   switch(table_index)
  931.   {
  932.   case RELOP_GE:
  933.     b = expr2();
  934.     if(a >= b) return 1;
  935.     break;
  936.   case RELOP_NE:
  937.   case RELOP_NE_BANG:
  938.     b = expr2();
  939.     if(a != b) return 1;
  940.     break;
  941.   case RELOP_GT:
  942.     b = expr2();
  943.     if(a > b) return 1;
  944.     break;
  945.   case RELOP_EQ:
  946.     b = expr2();
  947.     if(a == b) return 1;
  948.     break;
  949.   case RELOP_LE:
  950.     b = expr2();
  951.     if(a <= b) return 1;
  952.     break;
  953.   case RELOP_LT:
  954.     b = expr2();
  955.     if(a < b) return 1;
  956.     break;
  957.   }
  958.   return 0;
  959. }
  960.  
  961. /***************************************************************************/
  962. void loop()
  963. {
  964.   unsigned char *start;
  965.   unsigned char *newEnd;
  966.   unsigned char linelen;
  967.   boolean isDigital;
  968.   boolean alsoWait = false;
  969.   int val;
  970.  
  971. #ifdef ARDUINO
  972. #ifdef ENABLE_TONES
  973.   noTone( kPiezoPin );
  974. #endif
  975. #endif
  976.  
  977.   program_start = program;
  978.   program_end = program_start;
  979.   sp = program+sizeof(program);  // Needed for printnum
  980.   stack_limit = program+sizeof(program)-STACK_SIZE;
  981.   variables_begin = stack_limit - 27*VAR_SIZE;
  982.  
  983.   // memory free
  984.   printnum(variables_begin-program_end);
  985.   printmsg(memorymsg);
  986. #ifdef ARDUINO
  987. #ifdef ENABLE_EEPROM
  988.   // eprom size
  989.   printnum( E2END+1 );
  990.   printmsg( eeprommsg );
  991. #endif /* ENABLE_EEPROM */
  992. #endif /* ARDUINO */
  993.  
  994. warmstart:
  995.   // this signifies that it is running in 'direct' mode.
  996.   current_line = 0;
  997.   sp = program+sizeof(program);
  998.   printmsg(okmsg);
  999.  
  1000. prompt:
  1001.   if( triggerRun ){
  1002.     triggerRun = false;
  1003.     current_line = program_start;
  1004.     goto execline;
  1005.   }
  1006.  
  1007.   getln( '>' );
  1008.   toUppercaseBuffer();
  1009.  
  1010.   txtpos = program_end+sizeof(unsigned short);
  1011.  
  1012.   // Find the end of the freshly entered line
  1013.   while(*txtpos != NL)
  1014.     txtpos++;
  1015.  
  1016.   // Move it to the end of program_memory
  1017.   {
  1018.     unsigned char *dest;
  1019.     dest = variables_begin-1;
  1020.     while(1)
  1021.     {
  1022.       *dest = *txtpos;
  1023.       if(txtpos == program_end+sizeof(unsigned short))
  1024.         break;
  1025.       dest--;
  1026.       txtpos--;
  1027.     }
  1028.     txtpos = dest;
  1029.   }
  1030.  
  1031.   // Now see if we have a line number
  1032.   linenum = testnum();
  1033.   ignore_blanks();
  1034.   if(linenum == 0)
  1035.     goto direct;
  1036.  
  1037.   if(linenum == 0xFFFF)
  1038.     goto qhow;
  1039.  
  1040.   // Find the length of what is left, including the (yet-to-be-populated) line header
  1041.   linelen = 0;
  1042.   while(txtpos[linelen] != NL)
  1043.     linelen++;
  1044.   linelen++; // Include the NL in the line length
  1045.   linelen += sizeof(unsigned short)+sizeof(char); // Add space for the line number and line length
  1046.  
  1047.   // Now we have the number, add the line header.
  1048.   txtpos -= 3;
  1049.   *((unsigned short *)txtpos) = linenum;
  1050.   txtpos[sizeof(LINENUM)] = linelen;
  1051.  
  1052.  
  1053.   // Merge it into the rest of the program
  1054.   start = findline();
  1055.  
  1056.   // If a line with that number exists, then remove it
  1057.   if(start != program_end && *((LINENUM *)start) == linenum)
  1058.   {
  1059.     unsigned char *dest, *;
  1060.     unsigned tomove;
  1061.  
  1062.      = start + start[sizeof(LINENUM)];
  1063.     dest = start;
  1064.  
  1065.     tomove = program_end - ;
  1066.     while( tomove > 0)
  1067.     {
  1068.       *dest = *;
  1069.       ++;
  1070.       dest++;
  1071.       tomove--;
  1072.     }  
  1073.     program_end = dest;
  1074.   }
  1075.  
  1076.   if(txtpos[sizeof(LINENUM)+sizeof(char)] == NL) // If the line has no txt, it was just a delete
  1077.     goto prompt;
  1078.  
  1079.  
  1080.  
  1081.   // Make room for the new line, either all in one hit or lots of little shuffles
  1082.   while(linelen > 0)
  1083.   {    
  1084.     unsigned int tomove;
  1085.     unsigned char *,*dest;
  1086.     unsigned int space_to_make;
  1087.  
  1088.     space_to_make = txtpos - program_end;
  1089.  
  1090.     if(space_to_make > linelen)
  1091.       space_to_make = linelen;
  1092.     newEnd = program_end+space_to_make;
  1093.     tomove = program_end - start;
  1094.  
  1095.  
  1096.     // Source and destination - as these areas may overlap we need to move bottom up
  1097.      = program_end;
  1098.     dest = newEnd;
  1099.     while(tomove > 0)
  1100.     {
  1101.       --;
  1102.       dest--;
  1103.       *dest = *;
  1104.       tomove--;
  1105.     }
  1106.  
  1107.     // Copy over the bytes into the new space
  1108.     for(tomove = 0; tomove < space_to_make; tomove++)
  1109.     {
  1110.       *start = *txtpos;
  1111.       txtpos++;
  1112.       start++;
  1113.       linelen--;
  1114.     }
  1115.     program_end = newEnd;
  1116.   }
  1117.   goto prompt;
  1118.  
  1119. unimplemented:
  1120.   printmsg(unimplimentedmsg);
  1121.   goto prompt;
  1122.  
  1123. qhow:  
  1124.   printmsg(howmsg);
  1125.   goto prompt;
  1126.  
  1127. qwhat: 
  1128.   printmsgNoNL(whatmsg);
  1129.   if(current_line != NULL)
  1130.   {
  1131.     unsigned char tmp = *txtpos;
  1132.     if(*txtpos != NL)
  1133.       *txtpos = '^';
  1134.     list_line = current_line;
  1135.     printline();
  1136.     *txtpos = tmp;
  1137.   }
  1138.   line_terminator();
  1139.   goto prompt;
  1140.  
  1141. qsorry:
  1142.   printmsg(sorrymsg);
  1143.   goto warmstart;
  1144.  
  1145. run_next_statement:
  1146.   while(*txtpos == ':')
  1147.     txtpos++;
  1148.   ignore_blanks();
  1149.   if(*txtpos == NL)
  1150.     goto execnextline;
  1151.   goto interperateAtTxtpos;
  1152.  
  1153. direct:
  1154.   txtpos = program_end+sizeof(LINENUM);
  1155.   if(*txtpos == NL)
  1156.     goto prompt;
  1157.  
  1158. interperateAtTxtpos:
  1159.   if(breakcheck())
  1160.   {
  1161.     printmsg(breakmsg);
  1162.     goto warmstart;
  1163.   }
  1164.  
  1165.   scantable(keywords);
  1166.  
  1167.   switch(table_index)
  1168.   {
  1169.   case KW_DELAY:
  1170.     {
  1171. #ifdef ARDUINO
  1172.       expression_error = 0;
  1173.       val = expression();
  1174.       delay( val );
  1175.       goto execnextline;
  1176. #else
  1177.       goto unimplemented;
  1178. #endif
  1179.     }
  1180.  
  1181.   case KW_FILES:
  1182.     goto files;
  1183.   case KW_LIST:
  1184.     goto list;
  1185.   case KW_CHAIN:
  1186.     goto chain;
  1187.   case KW_LOAD:
  1188.     goto load;
  1189.   case KW_MEM:
  1190.     goto mem;
  1191.   case KW_NEW:
  1192.     if(txtpos[0] != NL)
  1193.       goto qwhat;
  1194.     program_end = program_start;
  1195.     goto prompt;
  1196.   case KW_RUN:
  1197.     current_line = program_start;
  1198.     goto execline;
  1199.   case KW_SAVE:
  1200.     goto save;
  1201.   case KW_NEXT:
  1202.     goto next;
  1203.   case KW_LET:
  1204.     goto assignment;
  1205.   case KW_IF:
  1206.     short int val;
  1207.     expression_error = 0;
  1208.     val = expression();
  1209.     if(expression_error || *txtpos == NL)
  1210.       goto qhow;
  1211.     if(val != 0)
  1212.       goto interperateAtTxtpos;
  1213.     goto execnextline;
  1214.  
  1215.   case KW_GOTO:
  1216.     expression_error = 0;
  1217.     linenum = expression();
  1218.     if(expression_error || *txtpos != NL)
  1219.       goto qhow;
  1220.     current_line = findline();
  1221.     goto execline;
  1222.  
  1223.   case KW_GOSUB:
  1224.     goto gosub;
  1225.   case KW_RETURN:
  1226.     goto gosub_return;
  1227.   case KW_REM:
  1228.   case KW_QUOTE:
  1229.     goto execnextline;  // Ignore line completely
  1230.   case KW_FOR:
  1231.     goto forloop;
  1232.   case KW_INPUT:
  1233.     goto input;
  1234.   case KW_PRINT:
  1235.   case KW_QMARK:
  1236.     goto print;
  1237.   case KW_POKE:
  1238.     goto poke;
  1239.   case KW_END:
  1240.   case KW_STOP:
  1241.     // This is the easy way to end - set the current line to the end of program attempt to run it
  1242.     if(txtpos[0] != NL)
  1243.       goto qwhat;
  1244.     current_line = program_end;
  1245.     goto execline;
  1246.   case KW_BYE:
  1247.     // Leave the basic interperater
  1248.     return;
  1249.  
  1250.   case KW_AWRITE:  // AWRITE <pin>, HIGH|LOW
  1251.     isDigital = false;
  1252.     goto awrite;
  1253.   case KW_DWRITE:  // DWRITE <pin>, HIGH|LOW
  1254.     isDigital = true;
  1255.     goto dwrite;
  1256.  
  1257.   case KW_RSEED:
  1258.     goto rseed;
  1259.  
  1260. #ifdef ENABLE_TONES
  1261.   case KW_TONEW:
  1262.     alsoWait = true;
  1263.   case KW_TONE:
  1264.     goto tonegen;
  1265.   case KW_NOTONE:
  1266.     goto tonestop;
  1267. #endif
  1268.  
  1269. #ifdef ARDUINO
  1270. #ifdef ENABLE_EEPROM
  1271.   case KW_EFORMAT:
  1272.     goto eformat;
  1273.   case KW_ESAVE:
  1274.     goto esave;
  1275.   case KW_ELOAD:
  1276.     goto eload;
  1277.   case KW_ELIST:
  1278.     goto elist;
  1279.   case KW_ECHAIN:
  1280.     goto echain;
  1281. #endif
  1282. #endif
  1283.  
  1284.   case KW_DEFAULT:
  1285.     goto assignment;
  1286.   default:
  1287.     break;
  1288.   }
  1289.  
  1290. execnextline:
  1291.   if(current_line == NULL)              // Processing direct commands?
  1292.     goto prompt;
  1293.   current_line +=        current_line[sizeof(LINENUM)];
  1294.  
  1295. execline:
  1296.   if(current_line == program_end) // Out of lines to run
  1297.     goto warmstart;
  1298.   txtpos = current_line+sizeof(LINENUM)+sizeof(char);
  1299.   goto interperateAtTxtpos;
  1300.  
  1301. #ifdef ARDUINO
  1302. #ifdef ENABLE_EEPROM
  1303. elist:
  1304.   {
  1305.     int i;
  1306.     for( i = 0 ; i < (E2END +1) ; i++ )
  1307.     {
  1308.       val = EEPROM.read( i );
  1309.  
  1310.       if( val == '\0' ) {
  1311.         goto execnextline;
  1312.       }
  1313.  
  1314.       if( ((val < ' ') || (val  > '~')) && (val != NL) && (val != CR))  {
  1315.         outchar( '?' );
  1316.       }
  1317.       else {
  1318.         outchar( val );
  1319.       }
  1320.     }
  1321.   }
  1322.   goto execnextline;
  1323.  
  1324. eformat:
  1325.   {
  1326.     for( int i = 0 ; i < E2END ; i++ )
  1327.     {
  1328.       if( (i & 0x03f) == 0x20 ) outchar( '.' );
  1329.       EEPROM.write( i, 0 );
  1330.     }
  1331.     outchar( LF );
  1332.   }
  1333.   goto execnextline;
  1334.  
  1335. esave:
  1336.   {
  1337.     outStream = kStreamEEProm;
  1338.     eepos = 0;
  1339.  
  1340.     // copied  "List"
  1341.     list_line = findline();
  1342.     while(list_line != program_end)
  1343.       printline();
  1344.  
  1345.     // go back to standard output, close the file
  1346.     outStream = kStreamSerial;
  1347.    
  1348.     goto warmstart;
  1349.   }
  1350.  
  1351.  
  1352. echain:
  1353.   runAfterLoad = true;
  1354.  
  1355. eload:
  1356.   // clear the program
  1357.   program_end = program_start;
  1358.  
  1359.   // load  a file into memory
  1360.   eepos = 0;
  1361.   inStream = kStreamEEProm;
  1362.   inhibitOutput = true;
  1363.   goto warmstart;
  1364. #endif /* ENABLE_EEPROM */
  1365. #endif
  1366.  
  1367. input:
  1368.   {
  1369.     unsigned char var;
  1370.     ignore_blanks();
  1371.     if(*txtpos < 'A' || *txtpos > 'Z')
  1372.       goto qwhat;
  1373.     var = *txtpos;
  1374.     txtpos++;
  1375.     ignore_blanks();
  1376.     if(*txtpos != NL && *txtpos != ':')
  1377.       goto qwhat;
  1378.     ((short int *)variables_begin)[var-'A'] = 99;
  1379.  
  1380.     goto run_next_statement;
  1381.   }
  1382.  
  1383. forloop:
  1384.   {
  1385.     unsigned char var;
  1386.     short int initial, step, terminal;
  1387.     ignore_blanks();
  1388.     if(*txtpos < 'A' || *txtpos > 'Z')
  1389.       goto qwhat;
  1390.     var = *txtpos;
  1391.     txtpos++;
  1392.     ignore_blanks();
  1393.     if(*txtpos != '=')
  1394.       goto qwhat;
  1395.     txtpos++;
  1396.     ignore_blanks();
  1397.  
  1398.     expression_error = 0;
  1399.     initial = expression();
  1400.     if(expression_error)
  1401.       goto qwhat;
  1402.  
  1403.     scantable(to_tab);
  1404.     if(table_index != 0)
  1405.       goto qwhat;
  1406.  
  1407.     terminal = expression();
  1408.     if(expression_error)
  1409.       goto qwhat;
  1410.  
  1411.     scantable(step_tab);
  1412.     if(table_index == 0)
  1413.     {
  1414.       step = expression();
  1415.       if(expression_error)
  1416.         goto qwhat;
  1417.     }
  1418.     else
  1419.       step = 1;
  1420.     ignore_blanks();
  1421.     if(*txtpos != NL && *txtpos != ':')
  1422.       goto qwhat;
  1423.  
  1424.  
  1425.     if(!expression_error && *txtpos == NL)
  1426.     {
  1427.       struct stack_for_frame *f;
  1428.       if(sp + sizeof(struct stack_for_frame) < stack_limit)
  1429.         goto qsorry;
  1430.  
  1431.       sp -= sizeof(struct stack_for_frame);
  1432.       f = (struct stack_for_frame *)sp;
  1433.       ((short int *)variables_begin)[var-'A'] = initial;
  1434.       f->frame_type = STACK_FOR_FLAG;
  1435.       f->for_var = var;
  1436.       f->terminal = terminal;
  1437.       f->step     = step;
  1438.       f->txtpos   = txtpos;
  1439.       f->current_line = current_line;
  1440.       goto run_next_statement;
  1441.     }
  1442.   }
  1443.   goto qhow;
  1444.  
  1445. gosub:
  1446.   expression_error = 0;
  1447.   linenum = expression();
  1448.   if(!expression_error && *txtpos == NL)
  1449.   {
  1450.     struct stack_gosub_frame *f;
  1451.     if(sp + sizeof(struct stack_gosub_frame) < stack_limit)
  1452.       goto qsorry;
  1453.  
  1454.     sp -= sizeof(struct stack_gosub_frame);
  1455.     f = (struct stack_gosub_frame *)sp;
  1456.     f->frame_type = STACK_GOSUB_FLAG;
  1457.     f->txtpos = txtpos;
  1458.     f->current_line = current_line;
  1459.     current_line = findline();
  1460.     goto execline;
  1461.   }
  1462.   goto qhow;
  1463.  
  1464. next:
  1465.   // Fnd the variable name
  1466.   ignore_blanks();
  1467.   if(*txtpos < 'A' || *txtpos > 'Z')
  1468.     goto qhow;
  1469.   txtpos++;
  1470.   ignore_blanks();
  1471.   if(*txtpos != ':' && *txtpos != NL)
  1472.     goto qwhat;
  1473.  
  1474. gosub_return:
  1475.   // Now walk up the stack frames and find the frame we want, if present
  1476.   tempsp = sp;
  1477.   while(tempsp < program+sizeof(program)-1)
  1478.   {
  1479.     switch(tempsp[0])
  1480.     {
  1481.     case STACK_GOSUB_FLAG:
  1482.       if(table_index == KW_RETURN)
  1483.       {
  1484.         struct stack_gosub_frame *f = (struct stack_gosub_frame *)tempsp;
  1485.         current_line    = f->current_line;
  1486.         txtpos                  = f->txtpos;
  1487.         sp += sizeof(struct stack_gosub_frame);
  1488.         goto run_next_statement;
  1489.       }
  1490.       // This is not the loop you are looking for... so Walk back up the stack
  1491.       tempsp += sizeof(struct stack_gosub_frame);
  1492.       break;
  1493.     case STACK_FOR_FLAG:
  1494.       // Flag, Var, Final, Step
  1495.       if(table_index == KW_NEXT)
  1496.       {
  1497.         struct stack_for_frame *f = (struct stack_for_frame *)tempsp;
  1498.         // Is the the variable we are looking for?
  1499.         if(txtpos[-1] == f->for_var)
  1500.         {
  1501.           short int *varaddr = ((short int *)variables_begin) + txtpos[-1] - 'A';
  1502.           *varaddr = *varaddr + f->step;
  1503.           // Use a different test depending on the sign of the step increment
  1504.           if((f->step > 0 && *varaddr <= f->terminal) || (f->step < 0 && *varaddr >= f->terminal))
  1505.           {
  1506.             // We have to loop so don't pop the stack
  1507.             txtpos = f->txtpos;
  1508.             current_line = f->current_line;
  1509.             goto run_next_statement;
  1510.           }
  1511.           // We've run to the end of the loop. drop out of the loop, popping the stack
  1512.           sp = tempsp + sizeof(struct stack_for_frame);
  1513.           goto run_next_statement;
  1514.         }
  1515.       }
  1516.       // This is not the loop you are looking for... so Walk back up the stack
  1517.       tempsp += sizeof(struct stack_for_frame);
  1518.       break;
  1519.     default:
  1520.       //printf("Stack is stuffed!\n");
  1521.       goto warmstart;
  1522.     }
  1523.   }
  1524.   // Didn't find the variable we've been looking for
  1525.   goto qhow;
  1526.  
  1527. assignment:
  1528.   {
  1529.     short int value;
  1530.     short int *var;
  1531.  
  1532.     if(*txtpos < 'A' || *txtpos > 'Z')
  1533.       goto qhow;
  1534.     var = (short int *)variables_begin + *txtpos - 'A';
  1535.     txtpos++;
  1536.  
  1537.     ignore_blanks();
  1538.  
  1539.     if (*txtpos != '=')
  1540.       goto qwhat;
  1541.     txtpos++;
  1542.     ignore_blanks();
  1543.     expression_error = 0;
  1544.     value = expression();
  1545.     if(expression_error)
  1546.       goto qwhat;
  1547.     // Check that we are at the end of the statement
  1548.     if(*txtpos != NL && *txtpos != ':')
  1549.       goto qwhat;
  1550.     *var = value;
  1551.   }
  1552.   goto run_next_statement;
  1553. poke:
  1554.   {
  1555.     short int value;
  1556.     unsigned char *address;
  1557.  
  1558.     // Work out where to put it
  1559.     expression_error = 0;
  1560.     value = expression();
  1561.     if(expression_error)
  1562.       goto qwhat;
  1563.     address = (unsigned char *)value;
  1564.  
  1565.     // check for a comma
  1566.     ignore_blanks();
  1567.     if (*txtpos != ',')
  1568.       goto qwhat;
  1569.     txtpos++;
  1570.     ignore_blanks();
  1571.  
  1572.     // Now get the value to assign
  1573.     expression_error = 0;
  1574.     value = expression();
  1575.     if(expression_error)
  1576.       goto qwhat;
  1577.     //printf("Poke %p value %i\n",address, (unsigned char)value);
  1578.     // Check that we are at the end of the statement
  1579.     if(*txtpos != NL && *txtpos != ':')
  1580.       goto qwhat;
  1581.   }
  1582.   goto run_next_statement;
  1583.  
  1584. list:
  1585.   linenum = testnum(); // Retuns 0 if no line found.
  1586.  
  1587.   // Should be EOL
  1588.   if(txtpos[0] != NL)
  1589.     goto qwhat;
  1590.  
  1591.   // Find the line
  1592.   list_line = findline();
  1593.   while(list_line != program_end)
  1594.     printline();
  1595.   goto warmstart;
  1596.  
  1597. print:
  1598.   // If we have an empty list then just put out a NL
  1599.   if(*txtpos == ':' )
  1600.   {
  1601.     line_terminator();
  1602.     txtpos++;
  1603.     goto run_next_statement;
  1604.   }
  1605.   if(*txtpos == NL)
  1606.   {
  1607.     goto execnextline;
  1608.   }
  1609.  
  1610.   while(1)
  1611.   {
  1612.     ignore_blanks();
  1613.     if(print_quoted_string())
  1614.     {
  1615.       ;
  1616.     }
  1617.     else if(*txtpos == '"' || *txtpos == '\'')
  1618.       goto qwhat;
  1619.     else
  1620.     {
  1621.       short int e;
  1622.       expression_error = 0;
  1623.       e = expression();
  1624.       if(expression_error)
  1625.         goto qwhat;
  1626.       printnum(e);
  1627.     }
  1628.  
  1629.     // At this point we have three options, a comma or a new line
  1630.     if(*txtpos == ',')
  1631.       txtpos++; // Skip the comma and move onto the next
  1632.     else if(txtpos[0] == ';' && (txtpos[1] == NL || txtpos[1] == ':'))
  1633.     {
  1634.       txtpos++; // This has to be the end of the print - no newline
  1635.       break;
  1636.     }
  1637.     else if(*txtpos == NL || *txtpos == ':')
  1638.     {
  1639.       line_terminator();        // The end of the print statement
  1640.       break;
  1641.     }
  1642.     else
  1643.       goto qwhat;      
  1644.   }
  1645.   goto run_next_statement;
  1646.  
  1647. mem:
  1648.   // memory free
  1649.   printnum(variables_begin-program_end);
  1650.   printmsg(memorymsg);
  1651. #ifdef ARDUINO
  1652. #ifdef ENABLE_EEPROM
  1653.   {
  1654.     // eprom size
  1655.     printnum( E2END+1 );
  1656.     printmsg( eeprommsg );
  1657.    
  1658.     // figure out the memory usage;
  1659.     val = ' ';
  1660.     int i;  
  1661.     for( i=0 ; (i<(E2END+1)) && (val != '\0') ; i++ ) {
  1662.       val = EEPROM.read( i );    
  1663.     }
  1664.     printnum( (E2END +1) - (i-1) );
  1665.    
  1666.     printmsg( eepromamsg );
  1667.   }
  1668. #endif /* ENABLE_EEPROM */
  1669. #endif /* ARDUINO */
  1670.   goto run_next_statement;
  1671.  
  1672.  
  1673.   /*************************************************/
  1674.  
  1675. #ifdef ARDUINO
  1676. awrite: // AWRITE <pin>,val
  1677. dwrite:
  1678.   {
  1679.     short int pinNo;
  1680.     short int value;
  1681.     unsigned char *txtposBak;
  1682.  
  1683.     // Get the pin number
  1684.     expression_error = 0;
  1685.     pinNo = expression();
  1686.     if(expression_error)
  1687.       goto qwhat;
  1688.  
  1689.     // check for a comma
  1690.     ignore_blanks();
  1691.     if (*txtpos != ',')
  1692.       goto qwhat;
  1693.     txtpos++;
  1694.     ignore_blanks();
  1695.  
  1696.  
  1697.     txtposBak = txtpos;
  1698.     scantable(highlow_tab);
  1699.     if(table_index != HIGHLOW_UNKNOWN)
  1700.     {
  1701.       if( table_index <= HIGHLOW_HIGH ) {
  1702.         value = 1;
  1703.       }
  1704.       else {
  1705.         value = 0;
  1706.       }
  1707.     }
  1708.     else {
  1709.  
  1710.       // and the value (numerical)
  1711.       expression_error = 0;
  1712.       value = expression();
  1713.       if(expression_error)
  1714.         goto qwhat;
  1715.     }
  1716.     pinMode( pinNo, OUTPUT );
  1717.     if( isDigital ) {
  1718.       digitalWrite( pinNo, value );
  1719.     }
  1720.     else {
  1721.       analogWrite( pinNo, value );
  1722.     }
  1723.   }
  1724.   goto run_next_statement;
  1725. #else
  1726. pinmode: // PINMODE <pin>, I/O
  1727. awrite: // AWRITE <pin>,val
  1728. dwrite:
  1729.   goto unimplemented;
  1730. #endif
  1731.  
  1732.   /*************************************************/
  1733. files:
  1734.   // display a listing of files on the device.
  1735.   // version 1: no support for subdirectories
  1736.  
  1737. #ifdef ENABLE_FILEIO
  1738.     cmd_Files();
  1739.   goto warmstart;
  1740. #else
  1741.   goto unimplemented;
  1742. #endif // ENABLE_FILEIO
  1743.  
  1744.  
  1745. chain:
  1746.   runAfterLoad = true;
  1747.  
  1748. load:
  1749.   // clear the program
  1750.   program_end = program_start;
  1751.  
  1752.   // load  a file into memory
  1753. #ifdef ENABLE_FILEIO
  1754.   {
  1755.     unsigned char *filename;
  1756.  
  1757.     // Work out the filename
  1758.     expression_error = 0;
  1759.     filename = filenameWord();
  1760.     if(expression_error)
  1761.       goto qwhat;
  1762.  
  1763. #ifdef ARDUINO
  1764.     // Arduino specific
  1765.     if( !SD.exists( (char *)filename ))
  1766.     {
  1767.       printmsg( sdfilemsg );
  1768.     }
  1769.     else {
  1770.  
  1771.       fp = SD.open( (const char *)filename );
  1772.       inStream = kStreamFile;
  1773.       inhibitOutput = true;
  1774.     }
  1775. #else // ARDUINO
  1776.     // Desktop specific
  1777. #endif // ARDUINO
  1778.     // this will kickstart a series of events to read in  the file.
  1779.  
  1780.   }
  1781.   goto warmstart;
  1782. #else // ENABLE_FILEIO
  1783.   goto unimplemented;
  1784. #endif // ENABLE_FILEIO
  1785.  
  1786.  
  1787.  
  1788. save:
  1789.   // save  memory out to a file
  1790. #ifdef ENABLE_FILEIO
  1791.   {
  1792.     unsigned char *filename;
  1793.  
  1794.     // Work out the filename
  1795.     expression_error = 0;
  1796.     filename = filenameWord();
  1797.     if(expression_error)
  1798.       goto qwhat;
  1799.  
  1800. #ifdef ARDUINO
  1801.     // remove the old file if it exists
  1802.     if( SD.exists( (char *)filename )) {
  1803.       SD.remove( (char *)filename );
  1804.     }
  1805.  
  1806.     // open the file, switch over to file output
  1807.     fp = SD.open( (const char *)filename, FILE_WRITE );
  1808.     outStream = kStreamFile;
  1809.  
  1810.     // copied  "List"
  1811.     list_line = findline();
  1812.     while(list_line != program_end)
  1813.       printline();
  1814.  
  1815.     // go back to standard output, close the file
  1816.     outStream = kStreamSerial;
  1817.  
  1818.     fp.close();
  1819. #else // ARDUINO
  1820.     // desktop
  1821. #endif // ARDUINO
  1822.     goto warmstart;
  1823.   }
  1824. #else // ENABLE_FILEIO
  1825.   goto unimplemented;
  1826. #endif // ENABLE_FILEIO
  1827.  
  1828. rseed:
  1829.   {
  1830.     short int value;
  1831.  
  1832.     //Get the pin number
  1833.     expression_error = 0;
  1834.     value = expression();
  1835.     if(expression_error)
  1836.       goto qwhat;
  1837.  
  1838. #ifdef ARDUINO
  1839.     randomSeed( value );
  1840. #else // ARDUINO
  1841.     srand( value );
  1842. #endif // ARDUINO
  1843.     goto run_next_statement;
  1844.   }
  1845.  
  1846. #ifdef ENABLE_TONES
  1847. tonestop:
  1848.   noTone( kPiezoPin );
  1849.   goto run_next_statement;
  1850.  
  1851. tonegen:
  1852.   {
  1853.     // TONE freq, duration
  1854.     // if either are 0, tones turned off
  1855.     short int freq;
  1856.     short int duration;
  1857.  
  1858.     //Get the frequency
  1859.     expression_error = 0;
  1860.     freq = expression();
  1861.     if(expression_error)
  1862.       goto qwhat;
  1863.  
  1864.     ignore_blanks();
  1865.     if (*txtpos != ',')
  1866.       goto qwhat;
  1867.     txtpos++;
  1868.     ignore_blanks();
  1869.  
  1870.  
  1871.     //Get the duration
  1872.     expression_error = 0;
  1873.     duration = expression();
  1874.     if(expression_error)
  1875.       goto qwhat;
  1876.  
  1877.     if( freq == 0 || duration == 0 )
  1878.       goto tonestop;
  1879.  
  1880.     tone( kPiezoPin, freq, duration );
  1881.     if( alsoWait ) {
  1882.       delay( duration );
  1883.       alsoWait = false;
  1884.     }
  1885.     goto run_next_statement;
  1886.   }
  1887. #endif /* ENABLE_TONES */
  1888. }
  1889.  
  1890. // returns 1 if the character is valid in a filename
  1891. static int isValidFnChar( char c )
  1892. {
  1893.   if( c >= '0' && c <= '9' ) return 1; // number
  1894.   if( c >= 'A' && c <= 'Z' ) return 1; // LETTER
  1895.   if( c >= 'a' && c <= 'z' ) return 1; // letter (for completeness)
  1896.   if( c == '_' ) return 1;
  1897.   if( c == '+' ) return 1;
  1898.   if( c == '.' ) return 1;
  1899.   if( c == '~' ) return 1;  // Window~1.txt
  1900.  
  1901.   return 0;
  1902. }
  1903.  
  1904. unsigned char * filenameWord(void)
  1905. {
  1906.   // SDL - I wasn't sure if this functionality existed above, so I figured i'd put it here
  1907.   unsigned char * ret = txtpos;
  1908.   expression_error = 0;
  1909.  
  1910.   // make sure there are no quotes or spaces, search for valid characters
  1911.   //while(*txtpos == SPACE || *txtpos == TAB || *txtpos == SQUOTE || *txtpos == DQUOTE ) txtpos++;
  1912.   while( !isValidFnChar( *txtpos )) txtpos++;
  1913.   ret = txtpos;
  1914.  
  1915.   if( *ret == '\0' ) {
  1916.     expression_error = 1;
  1917.     return ret;
  1918.   }
  1919.  
  1920.   // now, find the next nonfnchar
  1921.   txtpos++;
  1922.   while( isValidFnChar( *txtpos )) txtpos++;
  1923.   if( txtpos != ret ) *txtpos = '\0';
  1924.  
  1925.   // set the error code if we've got no string
  1926.   if( *ret == '\0' ) {
  1927.     expression_error = 1;
  1928.   }
  1929.  
  1930.   return ret;
  1931. }
  1932.  
  1933. /***************************************************************************/
  1934. static void line_terminator(void)
  1935. {
  1936.   outchar(NL);
  1937.   outchar(CR);
  1938. }
  1939.  
  1940. /***********************************************************/
  1941. void setup()
  1942. {
  1943. #ifdef ARDUINO
  1944.   Serial.begin(kConsoleBaud);   // opens serial port
  1945.   while( !Serial ); // for Leonardo
  1946.  
  1947.   Serial.println( sentinel );
  1948.   printmsg(initmsg);
  1949.  
  1950.   tft.begin();
  1951.  
  1952. #ifdef ENABLE_FILEIO
  1953.   initSD();
  1954.  
  1955. #ifdef ENABLE_AUTORUN
  1956.   if( SD.exists( kAutorunFilename )) {
  1957.     program_end = program_start;
  1958.     fp = SD.open( kAutorunFilename );
  1959.     inStream = kStreamFile;
  1960.     inhibitOutput = true;
  1961.     runAfterLoad = true;
  1962.   }
  1963. #endif /* ENABLE_AUTORUN */
  1964.  
  1965. #endif /* ENABLE_FILEIO */
  1966.  
  1967. #ifdef ENABLE_EEPROM
  1968. #ifdef ENABLE_EAUTORUN
  1969.   // read the first byte of the eeprom. if it's a number, assume it's a program we can load
  1970.   int val = EEPROM.read(0);
  1971.   if( val >= '0' && val <= '9' ) {
  1972.     program_end = program_start;
  1973.     inStream = kStreamEEProm;
  1974.     eepos = 0;
  1975.     inhibitOutput = true;
  1976.     runAfterLoad = true;
  1977.   }
  1978. #endif /* ENABLE_EAUTORUN */
  1979. #endif /* ENABLE_EEPROM */
  1980.  
  1981. #endif /* ARDUINO */
  1982. }
  1983.  
  1984.  
  1985. /***********************************************************/
  1986. static unsigned char breakcheck(void)
  1987. {
  1988. #ifdef ARDUINO
  1989.   if(Serial.available())
  1990.     return Serial.read() == CTRLC;
  1991.   return 0;
  1992. #else
  1993. #ifdef __CONIO__
  1994.   if(kbhit())
  1995.     return getch() == CTRLC;
  1996.   else
  1997. #endif
  1998.     return 0;
  1999. #endif
  2000. }
  2001. /***********************************************************/
  2002. static int inchar()
  2003. {
  2004.   int v;
  2005. #ifdef ARDUINO
  2006.  
  2007.   switch( inStream ) {
  2008.   case( kStreamFile ):
  2009. #ifdef ENABLE_FILEIO
  2010.     v = fp.read();
  2011.     if( v == NL ) v=CR; // file translate
  2012.     if( !fp.available() ) {
  2013.       fp.close();
  2014.       goto inchar_loadfinish;
  2015.     }
  2016.     return v;    
  2017. #else
  2018. #endif
  2019.      break;
  2020.   case( kStreamEEProm ):
  2021. #ifdef ENABLE_EEPROM
  2022. #ifdef ARDUINO
  2023.     v = EEPROM.read( eepos++ );
  2024.     if( v == '\0' ) {
  2025.       goto inchar_loadfinish;
  2026.     }
  2027.     return v;
  2028. #endif
  2029. #else
  2030.     inStream = kStreamSerial;
  2031.     return NL;
  2032. #endif
  2033.      break;
  2034.   case( kStreamSerial ):
  2035.   default:
  2036.     while(1)
  2037.     {
  2038.       if(Serial.available())
  2039.         return Serial.read();
  2040.     }
  2041.   }
  2042.  
  2043. inchar_loadfinish:
  2044.   inStream = kStreamSerial;
  2045.   inhibitOutput = false;
  2046.  
  2047.   if( runAfterLoad ) {
  2048.     runAfterLoad = false;
  2049.     triggerRun = true;
  2050.   }
  2051.   return NL; // trigger a prompt.
  2052.  
  2053. #else
  2054.   // otherwise. desktop!
  2055.   int got = getchar();
  2056.  
  2057.   // translation for desktop systems
  2058.   if( got == LF ) got = CR;
  2059.  
  2060.   return got;
  2061. #endif
  2062. }
  2063.  
  2064. /***********************************************************/
  2065. static void outchar(unsigned char c)
  2066. {
  2067.   if( inhibitOutput ) return;
  2068.  
  2069. #ifdef ARDUINO
  2070.   #ifdef ENABLE_FILEIO
  2071.     if( outStream == kStreamFile ) {
  2072.       // output to a file
  2073.       fp.write( c );
  2074.     }
  2075.     else
  2076.   #endif
  2077.   #ifdef ARDUINO
  2078.   #ifdef ENABLE_EEPROM
  2079.     if( outStream == kStreamEEProm ) {
  2080.       EEPROM.write( eepos++, c );
  2081.     }
  2082.     else
  2083.   #endif /* ENABLE_EEPROM */
  2084.   #endif /* ARDUINO */
  2085.     Serial.write(c);
  2086.  
  2087. #else
  2088.   putchar(c);
  2089. #endif
  2090. }
  2091.  
  2092. /***********************************************************/
  2093. /* SD Card helpers */
  2094.  
  2095. #if ARDUINO && ENABLE_FILEIO
  2096.  
  2097. static int initSD( void )
  2098. {
  2099.   // if the card is already initialized, we just go with it.
  2100.   // there is no support (yet?) for hot-swap of SD Cards. if you need to
  2101.   // swap, pop the card, reset the arduino.)
  2102.  
  2103.   if( sd_is_initialized == true ) return kSD_OK;
  2104.  
  2105.   // due to the way the SD Library works, pin 10 always needs to be
  2106.   // an output, even when your shield uses another line for CS
  2107.   pinMode(10, OUTPUT); // change this to 53 on a mega
  2108.  
  2109.   if( !SD.begin( kSD_CS )) {
  2110.     // failed
  2111.     printmsg( sderrormsg );
  2112.     return kSD_Fail;
  2113.   }
  2114.   // success - quietly return 0
  2115.   sd_is_initialized = true;
  2116.  
  2117.   // and our file redirection flags
  2118.   outStream = kStreamSerial;
  2119.   inStream = kStreamSerial;
  2120.   inhibitOutput = false;
  2121.  
  2122.   return kSD_OK;
  2123. }
  2124. #endif
  2125.  
  2126. #if ENABLE_FILEIO
  2127. void cmd_Files( void )
  2128. {
  2129.   File dir = SD.open( "/" );
  2130.   dir.seek(0);
  2131.  
  2132.   while( true ) {
  2133.     File entry = dir.openNextFile();
  2134.     if( !entry ) {
  2135.       entry.close();
  2136.       break;
  2137.     }
  2138.  
  2139.     // common header
  2140.     printmsgNoNL( indentmsg );
  2141.     printmsgNoNL( (const unsigned char *)entry.name() );
  2142.     if( entry.isDirectory() ) {
  2143.       printmsgNoNL( slashmsg );
  2144.     }
  2145.  
  2146.     if( entry.isDirectory() ) {
  2147.       // directory ending
  2148.       for( int i=strlen( entry.name()) ; i<16 ; i++ ) {
  2149.         printmsgNoNL( spacemsg );
  2150.       }
  2151.       printmsgNoNL( dirextmsg );
  2152.     }
  2153.     else {
  2154.       // file ending
  2155.       for( int i=strlen( entry.name()) ; i<17 ; i++ ) {
  2156.         printmsgNoNL( spacemsg );
  2157.       }
  2158.       printUnum( entry.size() );
  2159.     }
  2160.     line_terminator();
  2161.     entry.close();
  2162.   }
  2163.   dir.close();
  2164. }
  2165. #endif


Bele van rakva az LCD lib az *.ino mönyvtárba.
(#) ronin75 válasza borvendeg hozzászólására (») Márc 22, 2016
500W/12V=~42A+veszteségek. Igaz, hogy terheletlenül is kiég a biztosíték, de a táp indulása is megránthatja a biztosítékot. Át kell nézni az erősítőt, de a szövegkörnyezet alapján inkább átnézetni.
(#) Ronen válasza mpisti hozzászólására (») Márc 15, 2016
Értem. köszönöm a segítséget! Még szerencse hogy amikor hegesztem akkor nincs senki sem rajtam kívül itthon mert még egyedül lakom , így nincs evvel baj. szó mi szó van itthon még vasmagom csak azt még nem tudtam összeforgatni. hatalmas L-alakok, meg van egy ősrégi orosz mikrosütőből kiguberált nagy hipersil vasmag (kicsit ráférne viszont arra ragasztás. a vizes szabályozót azért is kellett megépítenem mert egy régi házban lakom ahol 10A az autómata, cserélni meg nem cserélik hacsak ki nem tetetem ilyen fura dobozba az órát ami meg 100 ezerbe lenne akkor viszont 32A-relét kaphatnék
(#) Spyro1411 hozzászólása Márc 6, 2016
Sziasztok!
Egy RGB led kontroller, ami 12A-t is képes elviselni. 15m szalag volt rákötve, két napig ment. Bekapcsolásnál villan egyet fehéren (összes szín felvillan) majd nem reagál a távirányító nymkodására. A cucc a tápra volt ráragasztva, elképzelhető, hogy érintkezett a két fémház. Valaki találkozott már ilyen problémával? Megéri javítani?
A válaszokat előre is köszönöm!
(#) h_tomek válasza VIM hozzászólására (») Feb 24, 2016
Szia!
2 éve vettük a lakást elég lepukkant állapotban. Eredetileg volt 25A automata az óránál.
Természetesen 1 fázis. Teljes körűen fel lett újítva az elektromos rendszer: minden helyiség konnektor külön biztosítva, minden helyiség világítás külön körön, klíma külön körön, sütő külön körön, stb. Mikor kész lett akkor gondoltam, hogy kérem a hálózat bővítést 32A-re.
2 évig nem volt gond semmivel.
Egy hét óta 3x fordult elő hogy levágta a 32A-es automatát.
Ebből 2X csak a mosogatógép ment, más szinte semmi. A mosogatógép 16A-es automatája nem oldott le.
Természetesen mielőtt kihívnám ez ELMŰ-t, le akarom mérni a tényleges fogyasztást lakatfogóval.
Néztem vezetékeket a bizti táblán: minden vezeték meg van húzva, nincs laza kábel.
A hétvégén lesz időm méricskélni, leírom majd a tapasztalatokat.

Köszönöm a hozzászólást!
(#) gyuszo válasza gyuszo hozzászólására (») Feb 23, 2016
A legtöbb szolgáltatónál ez a legkisebb elfogadott keresztmetszet, az alanyi 1 x 32A , valamint 3x10A miatt.
A hozzászólás módosítva: Feb 23, 2016
(#) Directors válasza kissattila88 hozzászólására (») Feb 21, 2016
A hangszóró TS paraméteri kellenek hozzá.
Itt egy példa. Bővebben: Link
A középső oszlopban lévő adatok kellenek. "Thiele & small parameters"
(#) zosza18 válasza maszek0005 hozzászólására (») Feb 15, 2016
Nos sikerült megegyezni a fickóval, kellett neki a megoldás. A hétvégén meg is csináltam készre, bár képeket nem nagyon csináltam, elfelejtettem mert nagyon siettem. A végső megoldás az első ötlet volt... 6eres kábel, 3 fázis, 1 föld, 2 a kapcsolójára. A váltónál van egy kicsi 16A-os csatlakozó, fölötte meg egy 6.3-as Jack aljzat. Bedugja a csatlakozót, bedugja a Jack-et és a gyári kapcsolóval mehet ugyan úgy. 5m-es lengőkábellel megcsinálva, hogy ne szűkölködjön. A váltót egy 3pontos talpra raktam fel egy kötődobozzal együtt, a tartóoszlopot középtájt eltoltam 8cm-t kb, 2X45°-al a súlypont miatt, így nekimehet az ember, nem borul semerre. raktam 2db fix 230-as aljzatot is, ha már volt hely, így nem kell hosszabbítózni annyit. A kapcsolóval lehet bekapcsolni az egészet, majd a gép saját kapcsolójáról indítható.

A beállításokról... A felfutási időt levettem 3mp-re, a leállítás 8mp-re. A többit megbeszéltük már, viszont... Édes kevés volt terhelve a tudása, így még belenyúltam. Bekapcsoltam az Autoboost-ot, a Torque boost-ot, felemeltem az áramot 12A-re, és engedtem 10%-os fesz. növelést is még neki. Ezek után már úgy viselkedett, ahogy egy ilyen kaliberű gépnek illik. A nagy tisztítókorongot vitte a kazánlemezen, de azért finoman kell bánni vele, nem szereti ha "ráfekszik a paraszt". Összefoglalva nagyon jó lett, és így van most már egy boldog tulajdonos is. Végezetül néhány kép is legyen, bár nem sok... Köszönöm a segítséget mégegyszer! További szép napot!

Üdv.: Zoli

Azért én is gondolkodom még a gyári megoldáson.
(#) kameleon2 válasza h_tomek hozzászólására (») Feb 15, 2016
Szia! Nálad nem feltétlenül a kismegszakítóval van a baj, hanem a fázisok egyidejűségével. Hány fázisod van? Ha egy - az mindent megmagyaráz. Nagyobb fogyasztókat több fázisra elosztva az egyidejűség kevesebb gondot okozna. Gondolj csak bele. Van mondjuk 3db fogyasztód 16A-re biztosítva. Egyesével megvan a fokozatosság is egy 32A-es kismegszakítóhoz képest. De ha mindhárom egyszerre működik, az eredő 3x16A=48A! A 32A-es kismegszakítónak le is kell oldania. A motorikus terhelések ráadásul induláskor 6-7 szeres áramot vesznek fel. Ha a mosógép mellé bedugod a porszívót és a bekapcsolás pillanatában vizsgálod - láthatod, hogy ugrani fog a betáp 32A-es biztije szintén. Pusztán a két motorikus terhelés és az egyidejűség hatására. Ráadásul nem mindegy ez az 50Hz melyik pillanatában történik. Ha nullátmenetnél - akár meg is úszhatod. Ha éppen telibe kapja a fázist a színusz tetejénél - akkor tuti megint, hogy lever az automata. Lágyindítós, nullátmenet kapcsolós elektronikájú porszívónál szintén megúszható a probléma.
Következő: »»   21 / 56
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem