Fórum témák

» Több friss téma
Fórum
Keresés
Lapozás: OK   8 / 197
(#) robis01 válasza HiMen hozzászólására (») Szept 14, 2023
Idézet:
„With distance more than approximately 5 feet (1.5 meters), you may need to use a powered USB hub, as the USB port on your computer does not supply enough power to stretch over distance.”


Dugd át egy nagy áramú (>500mA) USB portba akkor működnie kellene.
(#) tothtechnika2 hozzászólása Szept 8, 2023
Sziasztok! Adott egy ESP32. Letöltöttem arduinoban a legfrissebb könyvtárat hozzá (2.xxx) Osx alatt egyszerűen képtelenség beüzemelni. Sikerült ez itt bárkinek valahogy? Mindenféle python error van. Most már odáig eljutottam, hogy ez a hiba:
  1. Traceback (most recent call last):
  2.   File "esptool/loader.py", line 57, in <module>
  3.   File "PyInstaller/loader/pyimod02_importers.py", line 352, in exec_module
  4.   File "serial/tools/list_ports.py", line 31, in <module>
  5.   File "PyInstaller/loader/pyimod02_importers.py", line 352, in exec_module
  6.   File "serial/tools/list_ports_posix.py", line 33, in <module>
  7.   File "PyInstaller/loader/pyimod02_importers.py", line 352, in exec_module
  8.   File "serial/tools/list_ports_osx.py", line 26, in <module>
  9.   File "PyInstaller/loader/pyimod02_importers.py", line 352, in exec_module
  10.   File "ctypes/__init__.py", line 7, in <module>
  11. ImportError: dlopen(/var/folders/7_/p8pscx8x6f591tt7dc_ty4r00000gn/T/_MEIjJve7F/lib-dynload/_ctypes.cpython-38-darwin.so, 2): Symbol not found: _ffi_closure_alloc
  12.   Referenced from: /var/folders/7_/p8pscx8x6f591tt7dc_ty4r00000gn/T/_MEIjJve7F/lib-dynload/_ctypes.cpython-38-darwin.so (which was built for Mac OS X 10.15)
  13.   Expected in: /usr/lib/libffi.dylib
  14.  in /var/folders/7_/p8pscx8x6f591tt7dc_ty4r00000gn/T/_MEIjJve7F/lib-dynload/_ctypes.cpython-38-darwin.so
  15.  
  16. During handling of the above exception, another exception occurred:
  17.  
  18. Traceback (most recent call last):
  19.   File "esptool.py", line 31, in <module>
  20.   File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  21.   File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  22.   File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  23.   File "PyInstaller/loader/pyimod02_importers.py", line 352, in exec_module
  24.   File "esptool/__init__.py", line 41, in <module>
  25.   File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  26.   File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  27.   File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  28.   File "PyInstaller/loader/pyimod02_importers.py", line 352, in exec_module
  29.   File "esptool/cmds.py", line 14, in <module>
  30.   File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  31.   File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  32.   File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  33.   File "PyInstaller/loader/pyimod02_importers.py", line 352, in exec_module
  34.   File "esptool/bin_image.py", line 14, in <module>
  35.   File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  36.   File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  37.   File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  38.   File "PyInstaller/loader/pyimod02_importers.py", line 352, in exec_module
  39.   File "esptool/loader.py", line 62, in <module>
  40. AttributeError: module 'sys' has no attribute 'VERSION'
  41. [33007] Failed to execute script 'esptool' due to unhandled exception!
  42. exit status 1
  43. Hiba a(z) ESP32S3 Dev Module alaplapra fordításra.


Van valakinek ötlete mi lehet ez?
(#) Skori hozzászólása Szept 3, 2023
Hozzáértőket kérdezném.
Samsung PM883 SSD adatlapot nézem, konkrétan ezt: Bővebben: Link
A 8. oldal alján van egy ilyen paraméter:
Data Retention: 3months
notE:
1) Data retention was measured by assuming that SSD reaches the maximum rated endurance at 40'C in power-off state.

Jól értem, hogy kikapcsolt állapotban, 40°C-on tárolva, már 3 hónap után adatot veszthet??
A hozzászólás módosítva: Szept 3, 2023
(#) Koczur42 hozzászólása Aug 23, 2023
Helló!
Még kezdő vagyok, segítséget kérek. Újratelepítettem a Win10 és az Arduinot is.
Azóta az Arduino letöltésnél a következőket írja ki.

Avrdude: Stk_getaync{} attempt 10 of 10: not in sync: resp=0x00

Előre is köszönöm a segítséget.
Üdv: Koczur42
(#) pipi válasza Tambi hozzászólására (») Aug 20, 2023
The Timer/Counter Interrupt Mask register - TIMSK
4. Bit - OCIE1A: Timer/Counter1 Output CompareA Match Interrupt Enable
ebbe elég nehéz lenne egy egész bájtot(8bitet) beletölteni, ezért fúj szerintem.
De miért is ebbe a regiszterbe akarsz periódust tölteni?
A hozzászólás módosítva: Aug 20, 2023
(#) Tambi válasza asch hozzászólására (») Aug 19, 2023
Köszönöm kedves Kapu48!
Hasonló kóddal megpróbálkoztam ESP32-val, de az instabilabbnak tűnt. Nyilván az ismereteim alapján készíthető "legmagasabb szintű" kóddal, amiben egyszer olvasunk be analógot, és persze használjuk a tone funkciót...

Köszönöm kedves ASCH!
Néhány sort megpirosozott, de némi kiegészítéssel a mellékletig jutottam.

A fordító kifogása: Compilation error: lvalue required as left operand of assignment,
magyarul: Fordítási hiba: lvalue szükséges a hozzárendelés bal oldali operandusaként

Ez mit jelenthet, illetve mit tegyek?

Nem gondolom, hogy számít, de nincs csatlakoztatva a NANO a PC-hez...

Köszönettel; Tambi
A hozzászólás módosítva: Aug 19, 2023
(#) szs válasza SzilCsong hozzászólására (») Aug 18, 2023
Körte! Ezt nem írtad még
Ezt véletlen (tényleg véletlen) tudom.
Az úgy volt: a nejem vett Osonba olcsó LED-körtét, aztán otthon kiderült: 1000 ft-al többet fizetett érte, mint a polcon olvasta. Megnéztem a dobozt: rá volt írva, hogy szabályozható, és szó szerint úgy, a "dim" szócska szerepelt. De a pontos mondatra nem emlékszem. (Simán: valaki visszadobta, mint szokták -csak pont nem jó helyre. Még jó, hogy nem a virslik közé. Mert szokták úgy)
Tehát ha látod (és véletlen sem "not dim"), akkor dimmelhető.

Nekünk semmi szükségünk a dimmelhetőre, de csak ezért nem mentünk vissza Szigetszentmiklósra, hogy igenis cseréljük vissua az olcsóbra
(#) tibike32 hozzászólása Aug 18, 2023
Sziasztok !
Ezt az akvárium vezérlőt szeretném megépíteni: /aquacontrolaquacontrol .
Az Arduino Ide az ellenőrzéskor ezeket a hibákat írja ki :
In file included from d:\Documents\Arduino\libraries\esp8266-oled-ssd1306-3.2.5/SSD1306Wire.h:31,
from d:\Documents\Arduino\libraries\esp8266-oled-ssd1306-3.2.5/SSD1306.h:30,
from D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:35:
d:\Documents\Arduino\libraries\esp8266-oled-ssd1306-3.2.5/OLEDDisplay.h: In member function 'virtual bool OLEDDisplay::connect()':
d:\Documents\Arduino\libraries\esp8266-oled-ssd1306-3.2.5/OLEDDisplay.h:253:29: error: no return statement in function returning non-void [-Werror=return-type]
253 | virtual bool connect() {};
| ^
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino: At global scope:
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:61:41: error: 'PWMRANGE' was not declared in this scope
61 | unsigned int PWMdepth = PWMRANGE * 10; //PWMRANGE defaults to 1023 on ESP8266 in Arduino IDE
| ^~~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino: In function 'void setup()':
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:223:5: error: 'startAP' was not declared in this scope
223 | startAP();
| ^~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:256:17: error: 'now' was not declared in this scope; did you mean 'pow'?
256 | int endTime = now() + 30;
| ^~~
| pow
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:266:5: error: 'startAP' was not declared in this scope
266 | startAP();
| ^~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:322:8: error: 'defaultTimersAreLoaded' was not declared in this scope
322 | if ( defaultTimersAreLoaded() ) {
| ^~~~~~~~~~~~~~~~~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:414:21: error: 'getTimefromNTP' was not declared in this scope
414 | time_t result = getTimefromNTP();
| ^~~~~~~~~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:416:7: error: 'setTime' was not declared in this scope
416 | setTime( result );
| ^~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:428:34: error: 'localTime' was not declared in this scope; did you mean 'localtime'?
428 | Serial.println( formattedTime( localTime() ) );
| ^~~~~~~~~
| localtime
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:428:19: error: 'formattedTime' was not declared in this scope
428 | Serial.println( formattedTime( localTime() ) );
| ^~~~~~~~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:447:57: error: 'updateChannels' was not declared in this scope
447 | channelUpdateTimer.attach_ms( 1000 / updateFrequency, updateChannels ); // Finally set the timer routine to update the leds
| ^~~~~~~~~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:451:3: error: 'showHostname_IP_OLED' was not declared in this scope
451 | showHostname_IP_OLED();
| ^~~~~~~~~~~~~~~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino: In function 'void loop()':
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:473:5: error: 'showHostname_IP_OLED' was not declared in this scope
473 | showHostname_IP_OLED();
| ^~~~~~~~~~~~~~~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:483:41: error: 'now' was not declared in this scope; did you mean 'pow'?
483 | if ( !serverClient && nextSyncTime <= now() ) {
| ^~~
| pow
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:485:21: error: 'getTimefromNTP' was not declared in this scope
485 | time_t result = getTimefromNTP();
| ^~~~~~~~~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:487:7: error: 'setTime' was not declared in this scope
487 | setTime( result );
| ^~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:499:71: error: 'localTime' was not declared in this scope; did you mean 'localtime'?
499 | Serial.print( F("RAW HTTP @ ") ); Serial.print( formattedTime( localTime() ) ); Serial.print( F(" ") ); Serial.println( request );
| ^~~~~~~~~
| localtime
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:499:56: error: 'formattedTime' was not declared in this scope
499 | Serial.print( F("RAW HTTP @ ") ); Serial.print( formattedTime( localTime() ) ); Serial.print( F(" ") ); Serial.println( request );
| ^~~~~~~~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:506:7: error: 'fileSend' was not declared in this scope; did you mean 'fileno'?
506 | fileSend( "/index.htm" );
| ^~~~~~~~
| fileno
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:512:7: error: 'procesApiCall' was not declared in this scope
512 | procesApiCall( request );
| ^~~~~~~~~~~~~
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:517:7: error: 'fileSend' was not declared in this scope; did you mean 'fileno'?
517 | fileSend( request.substring( 4, request.lastIndexOf( " " ) ) );
| ^~~~~~~~
| fileno
D:\Documents\Akvarium\aquacontrol-master\aquacontrol-master\aquacontrol\aquacontrol.ino:527:3: error: 'updateOLEDbar' was not declared in this scope
527 | updateOLEDbar();
| ^~~~~~~~~~~~~
cc1plus.exe: some warnings being treated as errors

exit status 1

Compilation error: 'PWMRANGE' was not declared in this scope.

Tudnátok ebben segíteni ?

Tibi
(#) ptesza hozzászólása Aug 15, 2023
Sziasztok!

Bővebben: Link

Szeretnék egy kis segítséget kérni a hozzáértőktől. Egy ilyen ESP32 Arduino LVGL WIFI&Bluetooth Development Board 2.8" -ról lenne szó. Szeretnénk power bankról használni de minden egyes kipróbált power bank ledobja ha készenlétbe megy.
Valamilyen tápegységet szeretnénk építeni hozzá ami egy 18650 celláról tud menni.

Egyébként ebben az alkalmazásban szeretnénk használni mintegy hordozható kezelő, vagy távirányító.

Bővebben: Link
(#) Gafly válasza Régi motoros hozzászólására (») Aug 11, 2023
Az általad adott link utolsó kommentje pont erről szól:
Idézet:
„Device is not correctly display readings consumption (when 227в and 0,23а shows 14 Watt consumption), it can be as the calibrate?”

Itt is az az anyázás tárgya, hogy nem jött ki neki a matek:
227 x 0.23 = 52 és nem 14

Tedd rá üresen egy fogyasztásmérőre (ez is az elvileg), és nézd meg, hogy egy óra alatt mennyi Wh-t fogyaszt.
Az melegíti a transzformátort (a vasmagját leginkább).
(#) 444Tibi hozzászólása Aug 7, 2023
OFf de,

Mi a Joistent csinalnak a forummal,
tobb forumtarssal napok ota levelezel maganba, innen a topikbol is akku ugyben.
mai naptol nem enged valaszolni senkinek, not allowed....
"Ennek a szemelynek nem engedelyezett az uzenet"
Senkinek se...?? Mobilrol se, PC-rol se megy a privat uzenet. Mindenki nem tiltott le 12 ora leforgasa alatt az biztos.
(#) Ge Lee válasza Karesz 50 hozzászólására (») Aug 5, 2023
Fura is lett volna, ha egy bizti hangját hallod, két ellenállásét meg nem. Az olcsó kategóriában valóban nincsenek nagy különbségek. Beteszek ide egy képet ami nálam ezekről kialakult az évek során, ha csak egy embernek segítek vele már megérte. Balról jobbra megyünk, vagyis a legsilányabb hangot a 1206-os VIK produkálja ezekből, a legjobbat meg az a 2W-os akármi a jobb oldalon, azokhoz azért nincs gyártó írva mert nem tudom ki a gyártója.
Kicsik ugyan a különbségek, de ha azt nézzük, hogy a bal és a jobb oldal közt van mondjuk egy 10-es skálán 1 pont különbség (6 és7) akkor azért az nem is olyan kicsi. Hogy hol van a határ azt meg mindenki eldönti magának, csak az nagyon furán veszi ki magát amikor valaki határozott véleményt alkot egy alkatrészről úgy, hogy nem hogy nem próbálta, de még képen se látta.
Az a kis szénréteg pl. engem nagyon meglepett, régen az ilyeneket eldobáltam de legalábbis erősítőbe sosem raktam be, mondom szén, fúj, vacak, és nem hogy nem az, hanem az olcsó kategóriában az a legjobb, be is táraztam belőlük, hátha kell még valaha.
Állítólag a csúcs az a Shinkoh tantál de olyat ezen a fórumon biztosan nem sokan használnak mert 10-20 font + áfa darabja. Meg állítólag az AN ellenállásai is nagyon jók, de ott pl. az ezüst nióbium közel 50 font + áfa...
A felhasznált alkatrészek szerintem legalább 25%-ban meghatározzák egy erősítő hangját, és ez visszaköszön a gyári készülékekben is.
(#) Feri007 válasza pipi hozzászólására (») Aug 4, 2023
Az rs458/422 és az i2c nem összehasonlítható dolgok. Az rs458 csak a fizikai réteget definiálja,
az i2c az adatkapcsolatot (címzés, lekérdezés) is. Ezért is szeretjük.
Az i2c jeleket -ahhoz képest, ami egy kontrolleből jön, lehet robusztussá tenni.
Differenciálmódusuvá változtatni, feszültséget növelni. Ettől nem lesz rs458, de hasonlóan zajvédett lesz. Galvanikus izoláció nem feltétlen szükséges. Csavart érpáron nagyobb távolságú kommunikáció lehetséges ezáltal.
i2c-over-long-wires
Az idézett PCA9615 IC nem is drága, kapható is.
Egy másik, hasonló appnote: Bővebben: Link
(#) robis01 válasza MATA hozzászólására (») Júl 30, 2023
// note: RESET pin is used as a weak analog input for the set button and the NTC
// thermistor. You don't need to disable the RESET pin as the voltage won't
// go below 40% of Vcc.

Meg kell mérni a RESET lábon a feszültséget, benne kell legyen a határadatokban.

// RESET pin ADC values (tweak a little, if button/NTC do not work correctly)
#define NTCMIN 550 // lowest ADC value for NTC; below is a button press
#define NTCFAN 625 // turn on the fan if ADC value is below
#define NTCHOT 560 // show warning screen if ADC value is below

Ha nem működik jól a gomb akkor állítani kell az értékeken. Érdemes lenne kinyerni a programból az ADC adatokat, vagy ha az egyszerűbb írni kell egy ADC lekérdező programot, és a kapott adatok alapján beállítani a határértékeket.
(#) MATA hozzászólása Júl 30, 2023
Üdv mesterek!
A következő gondom lenne megépítettem ezt az áramkört működik is csak éppen nem lehet vagy csak véletlen lehet váltani a két kijelzés között a SET gombbal hiába nyomkodom.
https://oshwlab.com/wagiminator/y-attiny85-electronic-load
Itt van a kód is:
  1. // ===================================================================================
  2. // Project:   TinyLoad - Simple Electronic Constant Current Dummy Load (ATtiny45/85)
  3. // Version:   v1.2
  4. // Year:      2020 - 2021
  5. // Author:    Stefan Wagner
  6. // Github:    https://github.com/wagiminator
  7. // ===================================================================================
  8. //
  9. // Description:
  10. // ------------
  11. // The ATtiny measures voltage, current and temperature of the heat sink,
  12. // calculates power, energy and electric charge, controls the fan and displays
  13. // all relevant data on the OLED. The button is used to switch between
  14. // power/resistance and energy/charge display.
  15. //
  16. // References:
  17. // -----------
  18. // The I²C OLED implementation is based on TinyOLEDdemo
  19. //
  20. // OLED font was adapted from Neven Boyanov and Stephen Denne
  21. //
  22. // Wiring:
  23. // -------
  24. //                                   +-\/-+
  25. //     Button/NTC --- RST ADC0 PB5  1|°   |8  Vcc
  26. // Voltage Sensor ------- ADC3 PB3  2|    |7  PB2 ADC1 -------- OLED SCK
  27. // Current Sensor ------- ADC2 PB4  3|    |6  PB1 AIN1 OC0B --- Fan Control
  28. //                             GND  4|    |5  PB0 AIN0 OC0A --- OLED SDA
  29. //                                   +----+
  30. //
  31. // Compilation Settings:
  32. // ---------------------
  33. // Core:    ATtinyCore (https://github.com/SpenceKonde/ATTinyCore)
  34. // Board:   ATtiny25/45/85 (No bootloader)
  35. // Chip:    ATtiny45 or 85 (depending on your chip)
  36. // Clock:   1 MHz (internal)
  37. // B.O.D.:  2.7V
  38. //
  39. // Leave the rest on default settings. Don't forget to "Burn bootloader"!
  40. // No Arduino core functions or libraries are used. Use the makefile if
  41. // you want to compile without Arduino IDE.
  42. //
  43. // note: RESET pin is used as a weak analog input for the set button and the NTC
  44. //       thermistor. You don't need to disable the RESET pin as the voltage won't
  45. //       go below 40% of Vcc.
  46. //
  47. // Fuse settings: -U lfuse:w:0x62:m -U hfuse:w:0xd5:m -U efuse:w:0xff:m
  48. //
  49. // Operating Instructions:
  50. // -----------------------
  51. // The ADC of the ATtiny does its best to make the tinyLoad a pretty accurate
  52. // tool, but it might need a little calibration.
  53. //
  54. // How to calibrate:
  55. // Set ULCAL and ILCAL to "1" in the sketch, compile and upload.
  56. // Choose a stable input voltage of around 5V and turn the poti until the
  57. // display shows a current of around 0.7A. Measure the voltage and the current
  58. // with a trusty multimeter or a good lab bench power supply.
  59. // Calculate the voltage calibration factor as follows:
  60. // ULCAL = voltage measured with multimeter / voltage shown on OLED.
  61. // Calculate the current calibration factor as follows:
  62. // ILCAL = current measured with multimeter / current shown on OLED.
  63. // Set the ULCAL and ILCAL value in the sketch, compile and upload again.
  64. //
  65. // notes:
  66. // - Use a good heatsink with a 5V fan for the MOSFET!
  67. // - Be careful with high power loads! This device is called "tinyLoad" for a reason!
  68. // - Always turn the POTI full counter-clockwise before connecting the load!
  69. // - Due to the input offset voltage of the OpAmp the minimum load current is 17mA.
  70. // - The maximum load current is 4.5A, however for small voltages it might be less.
  71. // - Do not exceed the maximum voltage of 26V!
  72.  
  73.  
  74. // ===================================================================================
  75. // Libraries, Definitions and Macros
  76. // ===================================================================================
  77.  
  78. // Libraries
  79. #include <avr/io.h>                             // for GPIO
  80. #include <avr/sleep.h>                          // for sleep functions
  81. #include <avr/pgmspace.h>                       // for data stored in program memory
  82. #include <avr/interrupt.h>                      // for interrupts
  83. #include <util/delay.h>                         // for delays
  84.  
  85. // Pin assignments
  86. #define PIN_SDA       PB0                       // I2C serial data pin, connected to OLED
  87. #define PIN_SCL       PB2                       // I2C serial clock pin, connected to OLED
  88. #define PIN_FAN       PB1                       // pin connected to MOSFET for fan control
  89. #define PIN_VOLTAGE   PB3                       // pin for voltage measurement
  90. #define PIN_CURRENT   PB4                       // pin for current measurement
  91. #define PIN_NTC       PB5                       // pin connected to NTX and button
  92.  
  93. // Calibration values for internal 1.1V reference
  94. #define ULCAL         1                        // linear voltage calibration factor
  95. #define ILCAL         0.921                        // linear current calibration factor
  96.  
  97. // Parameter definitions
  98. #define MAXPOWER      15                        // max power in watt
  99. #define UCONV         11486336                  // voltage conversion = 1000*64*1023*R11/(R10+R11)
  100. #define ICONV         72019200                  // current conversion = 1000*64*1023*R_shunt*(R8+R9)/R9
  101.  
  102. // RESET pin ADC values (tweak a little, if button/NTC do not work correctly)
  103. #define NTCMIN        550                       // lowest ADC value for NTC; below is a button press
  104. #define NTCFAN        625                       // turn on the fan if ADC value is below
  105. #define NTCHOT        560                       // show warning screen if ADC value is below
  106.  
  107. // Pin manipulation macros
  108. #define pinInput(x)   DDRB  &= ~(1<<(x))        // set pin to INPUT
  109. #define pinOutput(x)  DDRB  |=  (1<<(x))        // set pin to OUTPUT
  110. #define pinLow(x)     PORTB &= ~(1<<(x))        // set pin to LOW
  111. #define pinHigh(x)    PORTB |=  (1<<(x))        // set pin to HIGH
  112. #define pinDisable(x) DIDR0 |=  (1<<(x))        // disable digital input buffer
  113. #define pinRead(x)    (PINB &   (1<<(x)))       // READ pin
  114. #define pinADC(x)     ((x)==2?1:((x)==3?3:((x)==4?2:0))) // convert pin to ADC port
  115.  
  116. // Pin to ADC port conversion macros
  117. #define AP_NTC        pinADC(PIN_NTC)           // ADC port of fan pin
  118. #define AP_CURRENT    pinADC(PIN_CURRENT)       // ADC port of current sense pin
  119. #define AP_VOLTAGE    pinADC(PIN_VOLTAGE)       // ADC port of voltage sense pin
  120.  
  121. // ===================================================================================
  122. // I2C Master Implementation (write only)
  123. // ===================================================================================
  124.  
  125. // I2C macros
  126. #define I2C_SDA_HIGH()  pinInput(PIN_SDA)       // release SDA   -> pulled HIGH by resistor
  127. #define I2C_SDA_LOW()   pinOutput(PIN_SDA)      // SDA as output -> pulled LOW  by MCU
  128. #define I2C_SCL_HIGH()  pinInput(PIN_SCL)       // release SCL   -> pulled HIGH by resistor
  129. #define I2C_SCL_LOW()   pinOutput(PIN_SCL)      // SCL as output -> pulled LOW  by MCU
  130.  
  131. // I2C transmit one data byte to the slave, ignore ACK bit, no clock stretching allowed
  132. void I2C_write(uint8_t data) {
  133.   for(uint8_t i=8; i; i--, data<<=1) {          // transmit 8 bits, MSB first
  134.     (data&0x80)?I2C_SDA_HIGH():I2C_SDA_LOW();   // SDA depending on bit
  135.     I2C_SCL_HIGH();                             // clock HIGH -> slave reads the bit
  136.     I2C_SCL_LOW();                              // clock LOW again
  137.   }
  138.   I2C_SDA_HIGH();                               // release SDA for ACK bit of slave
  139.   I2C_SCL_HIGH();                               // 9th clock pulse is for the ACK bit
  140.   I2C_SCL_LOW();                                // but ACK bit is ignored
  141. }
  142.  
  143. // I2C start transmission
  144. void I2C_start(uint8_t addr) {
  145.   I2C_SDA_LOW();                                // start condition: SDA goes LOW first
  146.   I2C_SCL_LOW();                                // start condition: SCL goes LOW second
  147.   I2C_write(addr);                              // send slave address
  148. }
  149.  
  150. // I2C stop transmission
  151. void I2C_stop(void) {
  152.   I2C_SDA_LOW();                                // prepare SDA for LOW to HIGH transition
  153.   I2C_SCL_HIGH();                               // stop condition: SCL goes HIGH first
  154.   I2C_SDA_HIGH();                               // stop condition: SDA goes HIGH second
  155. }
  156.  
  157. // ===================================================================================
  158. // OLED Implementation
  159. // ===================================================================================
  160.  
  161. // OLED definitions
  162. #define OLED_ADDR       0x78                    // OLED write address
  163. #define OLED_CMD_MODE   0x00                    // set command mode
  164. #define OLED_DAT_MODE   0x40                    // set data mode
  165. #define OLED_INIT_LEN   9                       // length of init command array
  166.  
  167. // Standard ASCII 5x8 font (adapted from Neven Boyanov and Stephen Denne)
  168. const uint8_t OLED_FONT[] PROGMEM = {
  169.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00,
  170.   0x14, 0x7F, 0x14, 0x7F, 0x14, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x23, 0x13, 0x08, 0x64, 0x62,
  171.   0x36, 0x49, 0x55, 0x22, 0x50, 0x00, 0x05, 0x03, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x00,
  172.   0x00, 0x41, 0x22, 0x1C, 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, 0x08, 0x08, 0x3E, 0x08, 0x08,
  173.   0x00, 0x00, 0xA0, 0x60, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x60, 0x60, 0x00, 0x00,
  174.   0x20, 0x10, 0x08, 0x04, 0x02, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x42, 0x7F, 0x40, 0x00,
  175.   0x42, 0x61, 0x51, 0x49, 0x46, 0x21, 0x41, 0x45, 0x4B, 0x31, 0x18, 0x14, 0x12, 0x7F, 0x10,
  176.   0x27, 0x45, 0x45, 0x45, 0x39, 0x3C, 0x4A, 0x49, 0x49, 0x30, 0x01, 0x71, 0x09, 0x05, 0x03,
  177.   0x36, 0x49, 0x49, 0x49, 0x36, 0x06, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x36, 0x36, 0x00, 0x00,
  178.   0x00, 0x56, 0x36, 0x00, 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14,
  179.   0x00, 0x41, 0x22, 0x14, 0x08, 0x02, 0x01, 0x51, 0x09, 0x06, 0x32, 0x49, 0x59, 0x51, 0x3E,
  180.   0x7C, 0x12, 0x11, 0x12, 0x7C, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x3E, 0x41, 0x41, 0x41, 0x22,
  181.   0x7F, 0x41, 0x41, 0x22, 0x1C, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x7F, 0x09, 0x09, 0x09, 0x01,
  182.   0x3E, 0x41, 0x49, 0x49, 0x7A, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x41, 0x7F, 0x41, 0x00,
  183.   0x20, 0x40, 0x41, 0x3F, 0x01, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x7F, 0x40, 0x40, 0x40, 0x40,
  184.   0x7F, 0x02, 0x0C, 0x02, 0x7F, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x4E, 0x71, 0x01, 0x71, 0x4E,
  185.   0x7F, 0x09, 0x09, 0x09, 0x06, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x7F, 0x09, 0x19, 0x29, 0x46,
  186.   0x46, 0x49, 0x49, 0x49, 0x31, 0x01, 0x01, 0x7F, 0x01, 0x01, 0x3F, 0x40, 0x40, 0x40, 0x3F,
  187.   0x1F, 0x20, 0x40, 0x20, 0x1F, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x63, 0x14, 0x08, 0x14, 0x63,
  188.   0x07, 0x08, 0x70, 0x08, 0x07, 0x61, 0x51, 0x49, 0x45, 0x43, 0x00, 0x7F, 0x41, 0x41, 0x00,
  189.   0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x7F, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04,
  190.   0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x01, 0x02, 0x04, 0x00, 0x20, 0x54, 0x54, 0x54, 0x78,
  191.   0x7F, 0x48, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0x20, 0x38, 0x44, 0x44, 0x48, 0x7F,
  192.   0x38, 0x54, 0x54, 0x54, 0x18, 0x08, 0x7E, 0x09, 0x01, 0x02, 0x18, 0xA4, 0xA4, 0xA4, 0x7C,
  193.   0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x44, 0x7D, 0x40, 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00,
  194.   0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78,
  195.   0x7C, 0x08, 0x04, 0x04, 0x78, 0x38, 0x44, 0x44, 0x44, 0x38, 0xFC, 0x24, 0x24, 0x24, 0x18,
  196.   0x18, 0x24, 0x24, 0x18, 0xFC, 0x7C, 0x08, 0x04, 0x04, 0x08, 0x48, 0x54, 0x54, 0x54, 0x20,
  197.   0x04, 0x3F, 0x44, 0x40, 0x20, 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x1C, 0x20, 0x40, 0x20, 0x1C,
  198.   0x3C, 0x40, 0x30, 0x40, 0x3C, 0x44, 0x28, 0x10, 0x28, 0x44, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,
  199.   0x44, 0x64, 0x54, 0x4C, 0x44, 0x08, 0x36, 0x41, 0x41, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00,
  200.   0x00, 0x41, 0x41, 0x36, 0x08, 0x08, 0x04, 0x08, 0x10, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
  201. };
  202.  
  203. // OLED init settings
  204. const uint8_t OLED_INIT_CMD[] PROGMEM = {
  205.   0xC8, 0xA1,                                   // flip screen
  206.   0xA8, 0x1F,                                   // set multiplex ratio
  207.   0xDA, 0x02,                                   // set com pins hardware configuration
  208.   0x8D, 0x14,                                   // set DC-DC enable
  209.   0xAF                                          // display on
  210. };
  211.  
  212. // OLED variables
  213. uint8_t OLED_x, OLED_y;                         // current cursor position
  214. const uint16_t DIVIDER[] PROGMEM = {10000, 1000, 100, 10, 1}; // BCD conversion array
  215.  
  216. // OLED init function
  217. void OLED_init(void) {
  218.   I2C_start(OLED_ADDR);                         // start transmission to OLED
  219.   I2C_write(OLED_CMD_MODE);                     // set command mode
  220.   for(uint8_t i = 0; i < OLED_INIT_LEN; i++)
  221.     I2C_write(pgm_read_byte(&OLED_INIT_CMD[i]));// send the command bytes
  222.   I2C_stop();                                   // stop transmission
  223. }
  224.  
  225. // OLED set the cursor
  226. void OLED_setCursor(uint8_t xpos, uint8_t ypos) {
  227.   I2C_start(OLED_ADDR);                         // start transmission to OLED
  228.   I2C_write(OLED_CMD_MODE);                     // set command mode
  229.   I2C_write(xpos & 0x0F);                       // set low nibble of start column
  230.   I2C_write(0x10 | (xpos >> 4));                // set high nibble of start column
  231.   I2C_write(0xB0 | (ypos & 0x07));              // set start page
  232.   I2C_stop();                                   // stop transmission
  233.   OLED_x = xpos; OLED_y = ypos;                 // set the cursor variables
  234. }
  235.  
  236. // OLED clear line
  237. void OLED_clearLine(uint8_t line) {
  238.   OLED_setCursor(0, line);                      // set cursor to line start
  239.   I2C_start(OLED_ADDR);                         // start transmission to OLED
  240.   I2C_write(OLED_DAT_MODE);                     // set data mode
  241.   for(uint8_t i=128; i; i--) I2C_write(0x00);   // clear the line
  242.   I2C_stop();                                   // stop transmission
  243. }
  244.  
  245. // OLED clear screen
  246. void OLED_clearScreen(void) {
  247.   for(uint8_t i=0; i<4; i++)                    // 4 lines
  248.     OLED_clearLine(i);                          // clear line
  249. }
  250.  
  251. // OLED plot a single character
  252. void OLED_plotChar(char c) {
  253.   uint16_t ptr = c - 32;                        // character pointer
  254.   ptr += ptr << 2;                              // -> ptr = (ch - 32) * 5;
  255.   I2C_write(0x00);                              // write space between characters
  256.   for(uint8_t i=5 ; i; i--) I2C_write(pgm_read_byte(&OLED_FONT[ptr++]));
  257.   OLED_x += 6;                                  // update cursor
  258.   if(OLED_x > 122) {                            // line end ?
  259.     I2C_stop();                                 // stop data transmission
  260.     OLED_setCursor(0,++OLED_y);                 // set next line start
  261.     I2C_start(OLED_ADDR);                       // start transmission to OLED
  262.     I2C_write(OLED_DAT_MODE);                   // set data mode
  263.   }
  264. }
  265.  
  266. // OLED print a string from program memory
  267. void OLED_printPrg(const char* p) {
  268.   I2C_start(OLED_ADDR);                         // start transmission to OLED
  269.   I2C_write(OLED_DAT_MODE);                     // set data mode
  270.   char ch = pgm_read_byte(p);                   // read first character from program memory
  271.   while(ch) {                                   // repeat until string terminator
  272.     OLED_plotChar(ch);                          // print character on OLED
  273.     ch = pgm_read_byte(++p);                    // read next character
  274.   }
  275.   I2C_stop();                                   // stop transmission
  276. }
  277.  
  278. // OLED print 8-bit value as 2-digit decimal (BCD conversion by substraction method)
  279. void OLED_printDec8(uint8_t value) {
  280.   uint8_t digitval = 0;                         // start with digit value 0
  281.   while(value >= 10) {                          // if current divider fits into the value
  282.     digitval++;                                 // increase digit value
  283.     value -= 10;                                // decrease value by divider
  284.   }
  285.   OLED_plotChar(digitval + '0');                // print first digit
  286.   OLED_plotChar(value + '0');                   // print second digit
  287. }
  288.  
  289. // OLED print 16-bit value as decimal (BCD conversion by substraction method)
  290. void OLED_printDec16(uint16_t value) {
  291.   uint8_t leadflag = 0;                         // becomes "1" on first digit
  292.   for(uint8_t digit = 0; digit < 5; digit++) {  // 5 digits
  293.     uint8_t digitval = 0;                       // start with digit value 0
  294.     uint16_t divider = pgm_read_word(&DIVIDER[digit]); // current divider
  295.     while(value >= divider) {                   // if current divider fits into the value
  296.       leadflag = 1;                             // end of leading spaces
  297.       digitval++;                               // increase digit value
  298.       value -= divider;                         // decrease value by divider
  299.     }
  300.     if(leadflag || (digit == 4)) OLED_plotChar(digitval + '0'); // print the digit
  301.     else OLED_plotChar(' ');                    // print leading space
  302.   }
  303. }
  304.  
  305. // OLED print float right-aligned
  306. void OLED_printValue(float value) {
  307.   value += 0.005;                               // for rounding
  308.   uint16_t front = value;                       // left side of decimal
  309.   uint8_t back = (value - front) * 100 ;        // right side of decimal
  310.   I2C_start(OLED_ADDR);                         // start transmission to OLED
  311.   I2C_write(OLED_DAT_MODE);                     // set data mode
  312.   OLED_printDec16(front);                       // print left side of decimal
  313.   OLED_plotChar('.');                           // print decimal
  314.   OLED_printDec8(back);                         // print right side of decimal
  315.   I2C_stop();                                   // stop transmission to OLED
  316. }
  317.  
  318. // ===================================================================================
  319. // Millis Counter Implementation for Timer0
  320. // ===================================================================================
  321.  
  322. volatile uint32_t MIL_counter = 0;              // millis counter variable
  323.  
  324. // Init millis counter
  325. void MIL_init(void) {
  326.   OCR0A  = 124;                                 // TOP: 124 = 1000kHz / (8 * 1kHz) - 1
  327.   TCCR0A = (1<<WGM01);                          // timer0 CTC mode
  328.   TCCR0B = (1<<CS01);                           // start timer0 with prescaler 8
  329.   TIMSK  = (1<<OCIE0A);                         // enable output compare match interrupt
  330. }
  331.  
  332. // Read millis counter
  333. uint32_t MIL_read(void) {
  334.   cli();                                        // disable interrupt for atomic read
  335.   uint32_t result = MIL_counter;                // read millis counter
  336.   sei();                                        // enable interrupts
  337.   return result;                                // return millis counter value
  338. }
  339.  
  340. // Timer0 compare match A interrupt service routine (every millisecond)
  341. ISR(TIM0_COMPA_vect) {
  342.   MIL_counter++;                                // increase millis counter
  343. }
  344.  
  345. // ===================================================================================
  346. // ADC Implementation
  347. // ===================================================================================
  348.  
  349. // Voltage references
  350. #define REFVCC    0                             // Vcc as reference
  351. #define REF1V1    (1<<REFS1)                    // internal 1.1V reference
  352. #define REF2V56   ((1<<REFS2) | (1<<REFS1))     // internal 2.56V reference
  353. #define AVBG      ((1<<MUX3)  | (1<<MUX2))      // port of internal bandgap (1.1V reference)
  354.  
  355. // ADC init
  356. void ADC_init(void) {
  357.   ADCSRA = (1<<ADPS1) | (1<<ADPS0)              // set ADC clock prescaler to 8
  358.          | (1<<ADEN)                            // enable ADC
  359.          | (1<<ADIE);                           // enable ADC interrupt
  360. }
  361.  
  362. // ADC add up several readings (oversampling) against choosen reference in sleep mode to denoise
  363. // max samples: 64
  364. uint16_t ADC_read(uint8_t port, uint8_t reference, uint8_t samples) {
  365.   uint16_t result = 0;                          // result
  366.   ADCSRA |= (1<<ADEN) | (1<<ADIF);              // enable ADC, turn off any pending interrupt
  367.   ADMUX   = (port & 0x0f) | reference;          // set input channel and reference
  368.   if(reference || (port==AVBG)) _delay_ms(2);   // wait 2ms to settle if Vref is used  
  369.   set_sleep_mode(SLEEP_MODE_ADC);               // sleep during sample for noise reduction
  370.   for(; samples; samples--) {                   // get several samples
  371.     sleep_mode();                               // go to sleep while taking ADC sample
  372.     while(ADCSRA & (1<<ADSC));                  // make sure sampling is completed
  373.     result += ADC;                              // add them up
  374.   }
  375.   return result;                                // return value
  376. }
  377.  
  378. // ADC interrupt service routine
  379. EMPTY_INTERRUPT(ADC_vect);                      // nothing to be done here
  380.  
  381. // ===================================================================================
  382. // Additional Functions
  383. // ===================================================================================
  384.  
  385. // Check if button is pressed
  386. uint8_t buttonPressed(void) {
  387.   uint16_t value = ADC_read(AP_NTC, REFVCC, 1);
  388.   return(value < NTCMIN);
  389. }
  390.  
  391. // Check if NTC is connected
  392. uint8_t NTCpresent(void) {
  393.   uint16_t value = ADC_read(AP_NTC, REFVCC, 1);
  394.   return( (value >= NTCMIN) && (value < 1020) );
  395. }
  396.  
  397. // ===================================================================================
  398. // Main Function
  399. // ===================================================================================
  400.  
  401. // Text strings stored in program memory
  402. const char StartScreen[] PROGMEM =
  403.   "-- TinyLoad  v1.2  --"
  404.   "Turn poti full CCW,  "
  405.   "connect the load and "
  406.   "press SET button.    ";
  407. const char WarnScreen[] PROGMEM =
  408.   "!!!!!  WARNING  !!!!!"
  409.   "You reached max power"
  410.   "  or temperature !   "
  411.   "!!! DECREASE LOAD !!!";
  412.  
  413. // Main function
  414. int main(void) {
  415.   // Local variables
  416.   uint16_t  vcc, vref2, onevolt, twovolt, rawCheck, temp;
  417.   float     rawVoltage, rawCurrent, voltage, current, power, resistance;
  418.   float     capacity = 0;
  419.   float     energy = 0;
  420.   uint8_t   primescreen = 1;
  421.   uint8_t   warnscreen;
  422.   uint8_t   lastbutton;
  423.   uint32_t  lastmillis, nowmillis, interval;
  424.  
  425.   // Setup
  426.   pinOutput(PIN_FAN);                                   // set output pins
  427.   pinDisable(PIN_NTC);                                  // disable digital input buffer
  428.   pinDisable(PIN_VOLTAGE);                              // disable digital input buffer
  429.   pinDisable(PIN_CURRENT);                              // disable digital input buffer
  430.   MIL_init();                                           // setup millis counter
  431.   ADC_init();                                           // setup ADC
  432.   OLED_init();                                          // prepare and start OLED
  433.   sei();                                                // enable global interrupts
  434.  
  435.   // Calibrate internal 2.56V reference
  436.   vref2 = ADC_read(AVBG, REF2V56, 64);                  // read internal bandgap against 2.56V reference
  437.   vref2 = (uint32_t)72019200 / vref2;                   // calculate Vref2 in mV; 72019200 = 64*1023*1100
  438.  
  439.   // Check if something is connected to the load
  440.   OLED_clearScreen();
  441.   OLED_setCursor(0,0);
  442.   OLED_printPrg(StartScreen);
  443.   while( (!buttonPressed()) && (ADC_read(AP_CURRENT, REF1V1, 1) < 10) );
  444.  
  445.   // Init some variables;
  446.   lastmillis = MIL_read();
  447.   lastbutton = 1;
  448.  
  449.   // Loop
  450.   while(1) {
  451.     vcc     = ADC_read(AVBG, REFVCC, 64);               // read internal bandgap against Vcc with 64 samples
  452.     vcc     = (uint32_t)72019200 / vcc;                 // calculate Vcc in mV; 1125300 = 64*1023*1100
  453.     onevolt = (uint32_t)1125300 / vcc;                  // calculate ADC-value for 1.1V
  454.     twovolt = (uint32_t)vref2 * 1023 / vcc;             // calculate ADC-value for 2.56V (calibrated)
  455.  
  456.     // Read and calculate voltage in V
  457.     rawCheck = ADC_read(AP_VOLTAGE, REFVCC, 1);         // get ADC-value for voltage reading
  458.     if (rawCheck < onevolt) {                           // check possibility of reading against 1.1V reference
  459.       rawVoltage  = ADC_read(AP_VOLTAGE, REF1V1, 64);   // read raw voltage against 1.1V reference
  460.       voltage     = rawVoltage * 1100 / UCONV * ULCAL;  // calculate real voltage value
  461.     }
  462.     else if (rawCheck < twovolt) {                      // check possibility of reading against 2.56V reference
  463.       rawVoltage  = ADC_read(AP_VOLTAGE, REF2V56, 64);  // read raw voltage against 2.56V reference
  464.       voltage     = rawVoltage * vref2 / UCONV * ULCAL; // calculate real voltage value
  465.     }
  466.     else {
  467.       rawVoltage  = ADC_read(AP_VOLTAGE, REFVCC, 64);   // read raw voltage against vcc
  468.       voltage     = rawVoltage * vcc / UCONV * ULCAL;   // calculate real voltage value
  469.     }
  470.  
  471.     // Read and calculate current in A
  472.     rawCheck = ADC_read(AP_CURRENT, REFVCC, 1);         // get ADC-value for current reading
  473.     if(rawCheck < onevolt) {                            // check possibility of reading against 1.1V reference
  474.       rawCurrent  = ADC_read(AP_CURRENT, REF1V1, 64);   // read raw current against 1.1V reference
  475.       current     = rawCurrent * 1100 / ICONV * ILCAL;  // calculate real current value
  476.     }
  477.     else if(rawCheck < twovolt) {                       // check possibility of reading against 2.56V reference
  478.       rawCurrent  = ADC_read(AP_CURRENT, REF2V56, 64);  // read raw current against 2.56V reference
  479.       current     = rawCurrent * vref2 / ICONV * ILCAL; // calculate real current value
  480.     }
  481.     else {
  482.       rawCurrent  = ADC_read(AP_CURRENT, REFVCC, 64);   // read raw current against vcc
  483.       current     = rawCurrent * vcc / ICONV * ILCAL;   // calculate real current value
  484.     }
  485.  
  486.     // Calculate power and resistance
  487.     power = voltage * current;                          // calculate power in W
  488.     if(current > 0) resistance = voltage / current;     // calculate resistance in Ohm
  489.     else resistance = 9999;                             // 9999 if no current
  490.     if(resistance > 9999) resistance = 9999;            // 9999 is max displayed value
  491.  
  492.     // Calculate energy/capacity in mWh and mAh
  493.     nowmillis  = MIL_read();
  494.     interval   = nowmillis - lastmillis;                // calculate time interval
  495.     lastmillis = nowmillis;
  496.     energy    += power   * interval / 3600;             // calculate mWh
  497.     capacity  += current * interval / 3600;             // calculate mAh
  498.  
  499.     // Turn on fan if needed
  500.     temp = ADC_read(AP_NTC, REFVCC, 1);
  501.     if( (power > 8) || ( (temp >= NTCMIN) && (temp < NTCFAN) ) ) pinHigh(PIN_FAN);
  502.     else pinLow(PIN_FAN);
  503.  
  504.     // Check limits
  505.     warnscreen = ( (power > MAXPOWER) || ( (temp >= NTCMIN) && (temp < NTCHOT) ) );
  506.  
  507.     // Check button
  508.     if (!lastbutton && buttonPressed()) primescreen = !primescreen;
  509.     lastbutton = buttonPressed();
  510.    
  511.     // Display values on the oled
  512.     OLED_setCursor(0,0);
  513.  
  514.     if(warnscreen) OLED_printPrg(WarnScreen);
  515.     else {
  516.       OLED_printPrg(PSTR("Voltage:   ")); OLED_printValue(voltage); OLED_printPrg(PSTR(" V"));
  517.       OLED_printPrg(PSTR("Current:   ")); OLED_printValue(current); OLED_printPrg(PSTR(" A"));
  518.  
  519.       if(primescreen) {
  520.         OLED_printPrg(PSTR("Power:     ")); OLED_printValue(power);      OLED_printPrg(PSTR(" W"));
  521.         OLED_printPrg(PSTR("Resistance:")); OLED_printValue(resistance); OLED_printPrg(PSTR(" O"));
  522.       }
  523.       else {
  524.         OLED_printPrg(PSTR("Energy:  ")); OLED_printValue(energy);   OLED_printPrg(PSTR(" mWh"));
  525.         OLED_printPrg(PSTR("Charge:  ")); OLED_printValue(capacity); OLED_printPrg(PSTR(" mAh"));
  526.       }
  527.     }
  528.     _delay_ms(50);
  529.   }
  530. }
(#) antiktelefon válasza ttindian hozzászólására (») Júl 28, 2023
Hahó! Már írtam, nem akarod megnézni a not connected lábra miért megy ellenállás?
(#) antiktelefon válasza gaboca323f hozzászólására (») Júl 27, 2023
Keress egy kész power bank panelt, ami tud usbc PD-t és egy kábelt ami triggereli a 20V-ot. Bontott vegyes celláknál ha nulláról építed legalább egy passzív balancer illene, mert nem ugyanúgy fognak merülni. Illetve kapacitást be kell mérd minden cellánál, hogy legalább nagyjából azonosak legyenek a tagok.
De ez messze a legjobb, mindent tud, balanszol, tölt, feszt kijelez, hővédelem meg mindenféle töltés mód.
Bővebben: Link
USB C PD triggeres kábel meg filléres és kapható mindenféle dc jackkel is.
A hozzászólás módosítva: Júl 27, 2023
(#) antiktelefon válasza Gafly hozzászólására (») Júl 27, 2023
A not connected lábra van valami kötve neki, ha jó a rajza és gyártó pinoutnál kiemeli arra nem szabad semmit kötni.
(#) erbe válasza robis01 hozzászólására (») Júl 25, 2023
Idézet:
„(not included)”

Erre nem is figyeltem, hogy csak egy üres tok.
(#) robis01 válasza erbe hozzászólására (») Júl 25, 2023
Nincs benne:

Idézet:
„Battery: 6x 18650(not included)”


Mondjuk így nem is hazudnak, mert képes 900Ah leadni, ha olyan aksit tesznek bele. Az hogy ilyen termék nincs a piacon arról az eladó nem tehet.
(#) Elektro.on válasza Peti817172M hozzászólására (») Júl 24, 2023
Szia!
Egy igen jó példa a Kínaiaknak ezen fajta hozzá állásához:

Power bank 900000 mAh

Azaz 900Ah . Savas autó akku ból tegyél egymás mellé átlagos 45Ah -s ból 20darabot....

A részletes leírásban viszont ott van a kimeneti paraméter: Max. 5V 2A
A hozzászólás módosítva: Júl 24, 2023
(#) Szaturnusz hozzászólása Júl 19, 2023
(#) Gafly válasza pipi hozzászólására (») Júl 19, 2023
Szerintem igazad van. Egyszer már kitárgyaltuk a kérdést mágneskapcsolókra vonatkozóan, de szerintem ugyanez igaz szelepekre is. Röviden: Az AC és DC között nem csak a tekercs menetszámában és huzalvastagságban van különbség, hanem konstrukcióban (maga a vasmag is más lehet, tartalmazva a rövidrezárt menetet, többek között) is.
Idézet:
„The working power of the AC relay is AC, and the working power of the DC relay is DC. The coil diameter of the AC relay is thicker and the number of turns is less, and the coil diameter of the DC relay has more turns than the thin wire diameter. The core of the AC relay has a short-circuit ring, and the DC does not. The cores of AC relays are mostly E-shaped, and the DC cores are cylindrical. The AC coil will generate heat due to eddy current and hysteresis loss in the iron core, so the coil has a skeleton to isolate the iron core from the coil, and the coil is made into a short and thick chunky type to dissipate heat from the coil and the iron core.

Most of the DC coils are thin and tall without a skeleton, so that the coil and the iron core are in direct contact with each other to facilitate heat dissipation. As far as the heating of the coil and the iron core is concerned, in the AC electromagnetic system, the iron core is a heating component, and there is a large gap between the coil and the coil, so as not to transmit heat to the coil, and the shape of the coil is short and thick, which is convenient for the iron core to dissipate heat; DC electromagnetic In the system, the coil is a heating component, there is no gap between it and the iron core, the iron core is used for heat dissipation, and the coil shape is slender, which is convenient for the coil itself to dissipate heat.”

Most csak ezt találtam, de talán pont elég.

Ha szerintem csak egy darab kell, és nincs bontott, akkor dugasztápot neki...
(#) icserny válasza KoblogPerGyok hozzászólására (») Júl 7, 2023
Szeretném felhívni szíves figyelmedet az ST Microelectronics AN4566 Extending the DAC performance of STM32 microcontrollers című "alkalmazási mintapéldájára".

A 2020. december 17-i és 2021. január 22-i előadásaimban bemutattam, hogy hogyan lehet az STM32F446RE mikrovezérlőjével DMA segítségével táblázattal adott adatokat kiküldeni szimultán két DAC csatornán. Engem a sebesség nem izgatott, tehát Timer6-tal ütemezett kiküldést kellene "áthangolni". A hozzászólásom elején említett iromány reményeim szerint űtbaigazítást ad, hogy melyik STM32 mikrovezérlőből mit és hogyan lehet kicsiholni (a sebességet illetően).
(#) benjami válasza KoblogPerGyok hozzászólására (») Júl 4, 2023
Megnéztem. Időzítő az nincs benne, de más időhúzó dolog az rendesen van benne:
  1. void IRAM_ATTR __dacWrite(uint8_t pin, uint8_t value)
  2. {
  3.     if(pin < 25 || pin > 26){
  4.         return;//not dac pin
  5.     }
  6.     pinMode(pin, ANALOG);
  7.     uint8_t channel = pin - 25;
  8.  
  9.  
  10.     //Disable Tone
  11.     CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN);
  12.  
  13.     if (channel) {
  14.         //Disable Channel Tone
  15.         CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN2_M);
  16.         //Set the Dac value
  17.         SET_PERI_REG_BITS(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_DAC, value, RTC_IO_PDAC2_DAC_S);   //dac_output
  18.         //Channel output enable
  19.         SET_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE);
  20.     } else {
  21.         //Disable Channel Tone
  22.         CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN1_M);
  23.         //Set the Dac value
  24.         SET_PERI_REG_BITS(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_DAC, value, RTC_IO_PDAC1_DAC_S);   //dac_output
  25.         //Channel output enable
  26.         SET_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);
  27.     }
  28. }
  29.  
  30. extern void dacWrite(uint8_t pin, uint8_t value) __attribute__ ((weak, alias("__dacWrite")));

Ez ugye minden alkalommal meghívja a pinMode függvényt, amiben ez van:
  1. extern void IRAM_ATTR __pinMode(uint8_t pin, uint8_t mode)
  2. {
  3.  
  4.     if(!digitalPinIsValid(pin)) {
  5.         return;
  6.     }
  7.  
  8.     uint32_t rtc_reg = rtc_gpio_desc[pin].reg;
  9.     if(mode == ANALOG) {
  10.         if(!rtc_reg) {
  11.             return;//not rtc pin
  12.         }
  13.         //lock rtc
  14.         uint32_t reg_val = ESP_REG(rtc_reg);
  15.         if(reg_val & rtc_gpio_desc[pin].mux){
  16.             return;//already in adc mode
  17.         }
  18.         reg_val &= ~(
  19.                 (RTC_IO_TOUCH_PAD1_FUN_SEL_V << rtc_gpio_desc[pin].func)
  20.                 |rtc_gpio_desc[pin].ie
  21.                 |rtc_gpio_desc[pin].pullup
  22.                 |rtc_gpio_desc[pin].pulldown);
  23.         ESP_REG(RTC_GPIO_ENABLE_W1TC_REG) = (1 << (rtc_gpio_desc[pin].rtc_num + RTC_GPIO_ENABLE_W1TC_S));
  24.         ESP_REG(rtc_reg) = reg_val | rtc_gpio_desc[pin].mux;
  25.         //unlock rtc
  26.         ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = ((uint32_t)2 << MCU_SEL_S) | ((uint32_t)2 << FUN_DRV_S) | FUN_IE;
  27.         return;
  28.     }
  29.  
  30.     //RTC pins PULL settings
  31.     if(rtc_reg) {
  32.         //lock rtc
  33.         ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
  34.         if(mode & PULLUP) {
  35.             ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_gpio_desc[pin].pullup) & ~(rtc_gpio_desc[pin].pulldown);
  36.         } else if(mode & PULLDOWN) {
  37.             ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_gpio_desc[pin].pulldown) & ~(rtc_gpio_desc[pin].pullup);
  38.         } else {
  39.             ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
  40.         }
  41.         //unlock rtc
  42.     }
  43.  
  44.     uint32_t pinFunction = 0, pinControl = 0;
  45.  
  46.     //lock gpio
  47.     if(mode & INPUT) {
  48.         if(pin < 32) {
  49.             GPIO.enable_w1tc = ((uint32_t)1 << pin);
  50.         } else {
  51.             GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
  52.         }
  53.     } else if(mode & OUTPUT) {
  54.         if(pin > 33){
  55.             //unlock gpio
  56.             return;//pins above 33 can be only inputs
  57.         } else if(pin < 32) {
  58.             GPIO.enable_w1ts = ((uint32_t)1 << pin);
  59.         } else {
  60.             GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32));
  61.         }
  62.     }
  63.  
  64.     if(mode & PULLUP) {
  65.         pinFunction |= FUN_PU;
  66.     } else if(mode & PULLDOWN) {
  67.         pinFunction |= FUN_PD;
  68.     }
  69.  
  70.     pinFunction |= ((uint32_t)2 << FUN_DRV_S);//what are the drivers?
  71.     pinFunction |= FUN_IE;//input enable but required for output as well?
  72.  
  73.     if(mode & (INPUT | OUTPUT)) {
  74.         pinFunction |= ((uint32_t)2 << MCU_SEL_S);
  75.     } else if(mode == SPECIAL) {
  76.         pinFunction |= ((uint32_t)(((pin)==1||(pin)==3)?0:1) << MCU_SEL_S);
  77.     } else {
  78.         pinFunction |= ((uint32_t)(mode >> 5) << MCU_SEL_S);
  79.     }
  80.  
  81.     ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;
  82.  
  83.     if(mode & OPEN_DRAIN) {
  84.         pinControl = (1 << GPIO_PIN0_PAD_DRIVER_S);
  85.     }
  86.  
  87.     GPIO.pin[pin].val = pinControl;
  88.     //unlock gpio
  89. }
  90.  
  91. extern void pinMode(uint8_t pin, uint8_t mode) __attribute__ ((weak, alias("__pinMode")));


Ezek után ne csodálkozz hogy ilyen lassú.
(#) dB_Thunder válasza KoblogPerGyok hozzászólására (») Júl 4, 2023
Idézet:
„Hát, ha nem kell regiszter szinten belenyúlni, akkor miért nem megy?”

Mert rosszul van megírva program!

Idézet:
„Nem elég output-ra állítani, azt is elrontom?”

Nem mind1 hogy és mikor állítod kimenetre! Nem vagyok programozás guru, de a mostani felállásban van rá esély, hogy az adott pinek bemenetek legyenek!
Ezért javasoltam, hogy az szükséges kimeneteket már a setup részben definiáld! Úgyis csak a DAC létra van ezekre kötve (gondolom)

Idézet:
„define-okkal megadott hexa értékek csak számok nekem. Gondolom valamelyik regisztereknek ad megfelelő értékeket mindegyik.”

Ez így van! Az adott hardver rész, jelen esetben az IO-k beállításait tartalmazza.

Idézet:
„meg kell-e pull down, vagy sem, lehet-e egyáltalán vagy sem. Én nem tudom, ezért kérdezem.”

Jó lenne ha ismernéd µC-k "I/O Pin Equivalent Schematic"-ját, magyarul az egyszerűsített kapcsolási rajzát! És értenél az elektrotechnikához, akkor már tudnál mindent!
ESP-hez nem találtam, de AtMega-hoz igen:
https://www.arnabkumardas.com/arduino-tutorial/gpio-register-description/

A DAC létra pontos működésékez kis impedanciás (max. pár ohm) logikai 1, vagy 0 kell! Ezt fel-, vagy lehúzó ellenállásokkal, "Open Drain" kimenettel nem lehet megcsinálni!

A fel- vagy lehúzó ellenállások használatának csak akkor van értelme, ha az adott pin-t bemenetként használjuk!
(#) KoblogPerGyok válasza kapu48 hozzászólására (») Júl 3, 2023
Köszi a választ, de még nem világos ez. Arduino, DSPIC,PIC -ben már sokat olvastam, meg használom is, de tudom, hogy sok időmbe telt, mire kibogarásztam a felépítését, ezért fordulok ide, mert aki sokat használta az ESP32-t az gyorsabban tudja kihámozni a megoldást.

A dokumentációban(727 oldalasban) a 76. oldalon ezt találtam a
"register 4.34. IO_MUX_x_REG (x: GPIO0­GPIO39) (0x10+4*x)"
fejezetben:

Idézet:
„FUN_WPD Pull-down enable of the pad. 1: internal pull-down enabled, 0: internal pull-down disabled. GPIO pins 34-39 are input-only. These pins do not feature an output driver or internal pullup/pull-down circuitry, therefore, their FUN_WPD is always 0. (R/W)”


Szóval elképzelhető, hogy az adott pin-re ezekel kell beállítani? Szóval mondjuk a GPIO12-nek ezen regiszterében a FUN_WPU -t nullára, míg a FUN_WPD-t 1 re kell állítani?

Mert ha jól értem, akkor a 34-39 pinre nem vonatkozik ez a driver. Ha lehúzom nullára az output lábakat a beéptett ellenállással, majd írok rá szoftverből, akkor megjelenik a logikai 3.3V?
Ez nem ezt csinálja?

És alapból 0 a regiszter értéke, azaz nem használ sem le, sem felhúzó ellenállást. A Z állapot nekem nem jó szerintem, mert az éppen logikai 0-n lévő lábaknak a földön kell lenniük.

Melyik regisztert kell még néznem, hogy egy adott pin output legyen?

Köszönöm a türelmeteket!
A hozzászólás módosítva: Júl 3, 2023
(#) pipi válasza etilalkohol hozzászólására (») Jún 25, 2023
A program tele van serial.print-el, arra voltam kiváncsi pontosan miket ír ki...
próbáld így:
https://esp32tutorials.com/esp32-sntp-esp-idf-synchronize-time-ntp/
  1. time_t now;
  2.     struct tm timeinfo;
  3.     time(&now);
  4.     localtime_r(&now, &timeinfo);
  5.     // Is time set? If not, tm_year will be (1970 - 1900).
  6.     if (timeinfo.tm_year < (2016 - 1900)) {
  7.         ESP_LOGI(TAG, "Time is not set yet. Connecting to WiFi and getting time over NTP.");
  8.         obtain_time();
  9.         // update 'now' variable with current time
  10.         time(&now);
  11.     }
  12. ...............

illetve 2016 helyett pl 2022
A hozzászólás módosítva: Jún 25, 2023
(#) adapter hozzászólása Jún 19, 2023
Sziasztok!
Olyan kérdésem lenne, hogy milyen alternatív email szolgáltatót ajánlanátok az alábbi szempontok alapján:
-ne legyen gmail
-nekem nem igen kell gazdag feature szett, extra funkciók (pl naptár, bigfile küldés stb.) azért nem baj ha valamennyire biztonságos
-ingyenes
opcionálisan: nem magyar domain (van olyan játék ami nem megy magyar domain-nel)
Természetesen van több email címem több szolgáltatónál, van amit kizárólag hivatalos helyeken használok (nav, ük, bank) van amit netes rendelésre másra nem, van amit céges ügyek intézésére. Gmailesem is van erre keresek alternatívát valójában.
Köszönöm
(#) Gafly válasza pipi hozzászólására (») Jún 17, 2023
Azt oldja meg a kondenzátor(bank).
Sajnos erre pont annyira van konkrét érték, mint az üzemi kondenzátorra.

Én prakitkusan megsergetném és terhelném.
De ugye a kérdező nem akar sok kondenzátort venni próbálkozáshoz.
Olyan képletet szeretne hallani, hogy például 15 nF x kW / MHz.

Itt van a levezetése öt oldalban.
A hozzászólás módosítva: Jún 17, 2023
Következő: »»   8 / 197
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