Tag Archives: ARM

ARM: MPU-6050™ paleidimas

Per visus tuos arduinus ir kitokius pitoninius iškrypimus, net kelias dienas nepaleidau MPU-6050™ akselerometro ir giroskopo. Pasirodo, reikia atidžiau skaityti produkto datašytą. O kad pas visokius arduinus mikroschema pasileidžia su ne pilna inicializacija ir konfiguracija aš nežinau. Bet mano variantas veikia ant gryno gcc.

STM32F103 MPU-6050™ source code, tik .c ir .h failai. Su nedideliu demo.

ARM55: TG12864H (ST7565) SPI

Tai dar vienas atmintinukas apie LCD ekraniukus. Tokie ekraniukai kogero eina iš kokio Ali, bet aš juos radau kažkokiuose kasos aparatuose. Iš įpatybių: Read Only, SPI.

Beveik viskas veikia naudojant standartines ST7565 bibliotekas, tačiau yra kažkoks bugas su inicializacija. Kol kas sprendimas- du kartus inicializuoti ekraniuką.

Kadangi nėra galimybės nuskaityti ekrano atminties, norint pasinaudoti grafinėmis funckijomis (taškai, nuskaityti tašką) reikia daryti šešėlinę atmintį (shadow ram) ir ten laikyti ekraniuko ekrano kopiją.

Veikiančios demo programos source code, STM32F103 procesoriukui, STM32CubeMX griaučiai.

ARM54: ADC AD7710

Seniai jau mėtėsi šis prabangus ADC- AD7710AR. Jis toks specifinis: aukštos įtampos maitinimas, beveik SPI ir 24 bitai.

Minimalus maitinimas- 5V, ir jo išėjimas labai arti 5V. Tačiau STM32F103 yra 5V tolerantiškas. Tačiau viskam yra ribos. MCU biški kaista. Todėl prie visų kojų nuosekliai pajungiau 64 omų rezistorius- gal kiek ir padėjo. Dar reikėtu dviejų maitinimo šaltinių- vienas skaitmenai (5V), o štai analoginei daliai kogero geriau net bipoliaris maitinimas. Tačiau iš bėdos galima prijungti prie 5V.

O štai su “SPI” interfeisu biški bėda. Primiausia čia pusė duplekso ir duomenys eina per tą patį laidą. STM32F103 lygtai ir palaiko tokį režimą, tačiau kelių dienų eksperimentai parodė, kad visdėlto neveikia. Arba CLK lieka pastoviai, arba nespėja persijungti ar tai nuskaito bet kokią informaciją. Ir dar, jaučiu problemos su mikroschemos greičiais.

O dabar dar viena kvailystė- jei nuskaitom duomenis kai įjungtas 16 bitų režimas, reikia ir skaityti tik 16 bitų, o jei skaitom 24, tai reikia ir skaityti 24. Ir dar reikia stebėti ar duomenys paruošti skaitymui. O dar yra kita kvailystė- atskiras valdymo pinas skaitymui ir rašymui, o ne vienas R/W pinas. Kodėl taip padaryta aš nežinau.

Internete neradau gyvo pavyzduko, kad viskas veiktu. Tačiau po eksperimentų gavosi, kad grynai “softwarinis” variantas puikiausiai veikia.

Čia eksperimentinis source kodas STM32F103 serijos mikroschemai AD7710. Pagrindas – STM32CubeMX.

P.S. čipo kaina biški nustebino.

Futaba VFD GU112x16G (ARM)

Dar biški VFD temos. Turiu kelis mažesnius grafinius VFD modulius: Futaba GU112x16G-7806A. Tai darvienas modulis suderinamas su standartiniu LCD moduliu. Tačiau tai kartu ir grafinis modulis.

Šiame eksperimente aš nejungiau modulio prie standartinio paralelinio interfeiso, o pabandžiau su alternatyvinius metodus: SPI ir su papildoma plokštele- I2C (PCF8574). I2C variantas lėtokas. SPI variantas gretas, jei naudoti papildomą MB laidą per pertraukima. Šis MCU tikrai per greitas šiam moduliui ir buvo bėdų. O jei naudoti su hardcoded užvėlinimu, papildomo laido nereikia. Per i2c ir taip viskas veikia lėtai, todėl nereikia nieko stebėti.

Kairėje SPI, dešinėje su papildomu kinišku moduliu, I2C.

Atkreipkite dėmesį, kad šis modulis naudoja visai kitokį SPI variantą nei didesnis modulis.

Demonstracinis source kodas SPI ir I2C variantams. STM32F103 procesoriui, cubeMX skeletas.

Futaba VFD GP9002A01A (ARM)

Nors realiai tai GP9002A02A. Man patinka VFD technologija. Keista spalva, didelis šviesumas ir kažkoks lempinis vaizdas. Todėl jei matau kur nors palaidą VFD ekraniuką, stengiuosi prigriebti. Aišku aš kalbu apie panaudojamus modulius, o ne kažkokius “custom made” iš senoviškų magnetofonų. O kiek kartų mačiau milžiniškus grafinius modulius kurie buvo sudaužyti- stiklinis korpusas neduoda tvirtumo. O šis modulis nukentėjo kitaip- jo trafukas su plonučiais laideliais atitrūko nuo transformatoriaus korpuso. Teko klijuoti ir užsiimti mikrochirurgija- trafukas visgi smd.

Tai grafinis ir tekstinis modulis. Galima pumpuoti binarinę informaciją arba galima naudotis integruotais šriftais ir kiek keistokais šrifto dydžiais. Ekranas kaip ir “grayscale”, bet man nepavyko. Gali būti, kad yra skirtumas tarp “01A” ir “02A”.

Futaba moduliai dažnai būna ne tik lygiagretaus interfeiso, kaip LCD moduliai, bet turi slaptus papildomus interfeisus: asinchroninis nuoseklusis (kaip RS232, tik TTL lygiai) ir SPI (synchronious serial). Asinchroninis dažnai būna per lėtas, net prie 115kbit matosi kaip formuojasi vaizdas. Paralelinis naudoja labai daug laidų, tačiau labai greitas. O štai SPI kaip ir kompromisas. Pas šį VFD maksimalus greitis kažkur 2Mbit. Nauji moduliai dažnai būna USB/HID- tokių dar nečiupinau.

Su STM32CubeMX sugeneruojam programos griaučius. Aš pasirinkau kojeles iš eilės. Procesoriukas- bet koks. Čia konkrečiai STM32F103VBT6. Kur kibirą turiu.

Mums be SPI, reikia CD (command/data), CS (chip select) ir jei norime gražiai animuoti: VFD_INT (čia kadrų sinchroimpulsas). CS – programinis, nes yra biški triukų. Net porą vakarų turėjau praleisti, kol pradėjo teisingai veikti. Trumpai- CS, CD ir SPI sekos svarbios!

Iš datašyto matom, kad SPI nėra defaultinis. Pirmiausia LSB, antriausia netipiniai CLK. Dar žiūrom į C/D.

VFD datasheet SPI

Labai padeda susigaudyti settinguose šis vogtas iš interneto paveikslėlis. Renkam tą kuris panašiausias:

Beveik visos komandos surašytos į programą. Aišku kiek užknisa ekrano atminties organizavimas, bet viską galima apeiti naudojant galingus MCU.

Ir aišku VFD ekrano valdymo source code STM32F103 procesoriui. (ARM-0053).

ARM48: USB HID host

Jei naudojamas STM32 čipas palaiko USB HOST režimą, tai prijungti USB įrenginį labai paprasta. Mano hardwarė labai paprasta- čipas ir dvi USB jungtys. Viena jungtis suprogramuota kaip virtualus COM portas skirta peržiūrėti rezultatus, o kita USB jungtis tai USB host. Čia galima prijungti pelę ir klavietūrą. Kiti HID įrenginiai nepalaikomi.
Primenu, kad HID klavietūra palaiko iki 6 klavišų nuspaudimus (neįskaitant modifikatorius: shift, control, alt…) ir atskirai siunčiami klavišų paspaudimai ir atleidimai.
Kad viskas veiktu, tereikia savo programoje pasirašyti callbacką:

  1. void USBH_HID_EventCallback(USBH_HandleTypeDef *phost)
  2. {
  3. char txt_buf[100];
  4. char t[4];
  5.  
  6. strcpy(t,"[x]");
  7. if(USBH_HID_GetDeviceType(phost) == HID_MOUSE) // if the HID is Mouse
  8. {
  9. HID_MOUSE_Info_TypeDef *Mouse_Info;
  10. Mouse_Info = USBH_HID_GetMouseInfo(phost); // Get the info
  11. int8_t dX_Val = Mouse_Info->x; // get the delta x value (note unsigned - signed conversion)
  12. int8_t dY_Val = Mouse_Info->y; // get the delta y value
  13.  
  14. int len = sprintf (txt_buf, "dX=%d, dY=%d, Button1=%d, Button2=%d, Button3=%d\r\n", dX_Val, dY_Val, Mouse_Info->buttons[0],Mouse_Info->buttons[1], Mouse_Info->buttons[2]);
  15. user_usb_tx((uint8_t *) txt_buf,len);
  16. }
  17. if(USBH_HID_GetDeviceType(phost) == HID_KEYBOARD)
  18. {
  19.  
  20. HID_KEYBD_Info_TypeDef *Keyboard_Info;
  21. Keyboard_Info = USBH_HID_GetKeybdInfo(phost); // get the info
  22. txt_buf[0]=0;
  23. unsigned char i;
  24. for(i=0;i<6;i++)
  25. {
  26. if(Keyboard_Info->keys[i] != OLDKEYS[i] )
  27. {
  28. if (Keyboard_Info->keys[i]==0) {strcat(txt_buf,"UPKEY:"); hex8(txt_buf,OLDKEYS[i]);t[1]=Scan2Char(OLDKEYS[i]); strcat(txt_buf,t);}
  29. else if (OLDKEYS[i]==0) {strcat(txt_buf,"DOWNKEY:"); hex8(txt_buf,Keyboard_Info->keys[i]);t[1]=Scan2Char(Keyboard_Info->keys[i]); strcat(txt_buf,t);}
  30. else {strcat(txt_buf,"ERR:"); hex8(txt_buf,Keyboard_Info->keys[i]); strcat(txt_buf,"-");hex8(txt_buf,OLDKEYS[i]);}
  31. }
  32. OLDKEYS[i]=Keyboard_Info->keys[i];
  33. }
  34. strcat(txt_buf,"\r\n");
  35. user_print_usb( txt_buf);
  36. }
  37. }

Pačiam HID reporte visada transliuojami visi nuspausti klavišai, todėl, jei reikia susiderinti su PS2 ar senesniu standartu, reikia tikrinti, koks klavišas nuspaustas ir koks paleistas. Ta daro ciklas 24-33 eilutėse.
Rezultatas:


UPKEY:12[o]
DOWNKEY:13[p]
UPKEY:13[p]
DOWNKEY:2F[[]
UPKEY:2F[[]
DOWNKEY:30[]]
UPKEY:30[]]
DOWNKEY:31[\]
UPKEY:31[\]
DOWNKEY:04[q]
DOWNKEY:16[s]
DOWNKEY:07[d]
DOWNKEY:09[f]


DOWNKEY:2C[ ]
UPKEY:16[s]
UPKEY:07[d]
UPKEY:09[f]
UPKEY:04[q]
UPKEY:2C[ ]
DOWNKEY:0B[h]
UPKEY:0B[h]

Visas demo softo source code čia: STM32CubeMX USB host HID demo source code.

ARM47 ir PID dalis #4

O dabar pašnekėsim apie STM32F4 serijos variantą ir source code. Pirmiausia- kodėl 4 serija? Todėl, kad tokia PCB pasitaikė po ranka. Ir tikrai ne dėl kažkokio mistinio FPU ar net DSP. Ir dar neaišku, ar mano turimas MCU yra originalas, o ne koks nors permarkiruotas šlamštas. Šaltinis solidus, bet kodėl jie juos išmetė? Reikia surasti kur nors panaudotą procesorių ir palyginti.

Source code yra sugeneruotas su CubeMX programa, kompiliuota su gcc. Ryšiai su kubiko paprogramėm tik per callback. Ir tai tik naudojam USB biblioteką (virtualus COM portas) ir taimerių pertraukimus. ADC skaitom blokavimo režime.

Pats PID skaičiavimas, float variantas visiškai toks pats kaip ir teoriniam variante:

float pid_generic(float measured, float setpoint, float amplif)
{
float output;
float deritative;
float error;
float proportional;
 
error = (setpoint - measured)/10;
proportional = error;
 
integral=integral + error * pid_dt;
deritative = (error - old_error) / pid_dt;
old_error = error;
 
output = (PID_KP * proportional + PID_KI * integral + PID_KD * deritative) * amplif;
 
return output;
}

Atsirado papildomas parametras “amplif” – tai bendro rezultato daugiklis, kaip ir sustiprinimas (ar susilpninimas). Teoriškai tą patį galima atlikti su pagrindiniais parametrais (P, I, D), bet taip lengviau priderinti prie “krosnelės” galingumo: kaitinimas dirba su integer skaičiais, ir PID rezultatas apsiapvalina. Taip prarandam “jautrumą”. Ir dar temperatūros parodymus pasmulkinam- tik dėl koeficientų.

uint32_t CalcTemp(void)
{
uint32_t a;
a=median_filter(adc_read_blocking(ADC_CHANNEL_4));
a=median_filter(adc_read_blocking(ADC_CHANNEL_4));
//a=median_filter(adc_read_blocking(ADC_CHANNEL_4));
// 786 - max t, 0.62V ->1655
// 3529 - kambario t, 2.83V -> 283
return (4096-a)/2; //12 bitų max apverčiam ir pašalinam LSB.
}
 

Dėl ADC blogumo, matuojam kelis kartus, invertuojam (dėl schemotechnikos išėjimas mažėja didėjant temperatūrai) ir pašalinam mažiausią bitą, nes jis rodo kvailystes. Funkcija “median filter” vogta iš interneto. Tai funkcija, kuri teoriškai turi išfiltruoti sporadiškus nukrypimus: jei eina 5, 6, 4, 3, 100 – tai tas šimtas kaip ir ne į temą. Kiek veikia per daug netikrinau. Manau, reikia dar padidinti buferį.

  1. readtemp=CalcTemp();
  2. pwm=PID(readtemp, SETTEMP);
  3. SetPWM(pwm);

O čia pats pagrindinis ciklas, kuris kartojamas sistemingai: 1 – nuskaitom, 2 – paskaičiuojam. 3 – valdom kaitinimą.

Visas likęs source kodas aptarnauja kontrolerio valdymą per terminalą (galima keisti parametrus) ir duomenų išmetimą analizei. Tai tik eksperimentinis variantas- darbiniam trūksta dar visokių apsaugų, normalaus valdymo ir indikacijos. Ir aišku, išėjimas čia PWM, kad tinkama mažam rezistoriui, bet ne tikram šildytuvui. Dar nesugalvojau, kaip padaryti korektiškai proporcinį valdymą realiai rėlei ar 50Hz simistoriniam reguliatoriui. Jei užteks kantrybės, tema bus vystoma.

Pats pilnas STM32F446 PID controller source code skirtas gcc ir kartu CubeMX projekto failas (versija užrakinta posto datai, galimi patobulinimai). Prie papildų- median filter, ftoa ir usb paprogramės. Visa mano kūryba “USER” aplanke.

PID, dalis #3, FLOAT ir STM32F4

Dabar, apjungiant senesnius straipsnius [0, 1, 2], sumontavau kažką panašaus į PID termokontrolerį.

PID controller STM32F4xx

Ant lentos surinkta mano universali White Pill plokštė, tik su STM32F446 procesorium (toks biški itartinas tas procesoriukas, kažko man taimeriai neteisingai veikia). Dešinėje- mano Pt100 termorezistoriaus stiprintuvas. Geltona plokštė, tai kiek pasvilęs RGB LED “stiprintuvas”- galvaniškai atrišti trys galingi MOSFET valdomi per optoporas. Optoporų rezistorių teko sumažinti, kad nuo 3V procesoriuko pilnai valdytusi. O vienas “RGB LED stiprintuvo” kanalų paprasčiausiai valdo vielinį rezistorių kairėje, į kurį įkištas Pt100 jutiklis- tai mikro krosnelė, kurioje bandysim stabilizuoti temperatūrą.

Šiame eksperimente naudojamas source code su “float” kintamaisiais. Nenorėjau iškarto eksperimentuoti su integer matematika, nes dar nežinojau savo “krosnelės” parametrų.

PID įėjimas- ADC, išėjimas PWM. Panaudojau “prabangų”, 16 bitų PWM, nes norėjau platesnio reguliavimo. O su ADC išėjo biški problematiškai- STM32F446 ADC biški gaidiškas (net jo datašytas tai rašo). Nėra jokio tikslumo ir rezultatai vaikšto. Todėl panaudojau matematinį “filtrą” ir kelis nuskaitymus iš karto. Temperatūra matuojama “papūgomis”1 – 1000 vienetų tai kažkur 40℃, o apie 280 tai kažkur kambario. Užduotis- palaikyti 1000 vienetų temperatūrą viduje rezistoriaus.

Pagrindinė bėda- tiek rezistorius, tiek Pt100 žiauriai lėtai veikia. Todėl teko gana ilgai žaisti su koeficientais, ir dar iki optimalumo jie neprivesti.

PID chart

Mėlynas grafikas- rezistoriaus temperatūra. Raudonas grafikas PWM užpildymas. Matosi periodiniai triukšmai tiek temperatūros nuskaityme, tiek išeinančiam signale. Reikia rimtesnio skaitmeninio filtro. Dar kiek palaikius, paskutinius 400+ skaitymų temperatūros vidurkis buvo lygiai 1000 papūgų. Tačiau signalas nesusistabilizavo. Gal per maža PWM reikšmė:

PID PWM

Vos 2% iš viso. Gal vėliau pabandysiu su aukštesne temperatūra. (PWM signalas iš MOSFETO- žemas lygis reiškia, kad rezistorius prijungtas prie žemės ir kaista). Beja, gal ir siauresnis signalas per siauras šiems kiniškiems mosfetams. Pastebėjau, kad prie mažesnių signalų, PWM dingsta iš oscilografo ekrano.

Pratesimas ir veikiantis source code sekančiam straipsnyje.

  1. Tai santykinis matvimo vienetas iš seno multifilmo, kai matavo smauglio ilgį. ↩︎

ARM46: WS2812 RBG LED juostelė kitaip

Prieš septynius metus rašiau apie WS2812 RGB LED juostelę ir kaip ją valdyti su AVR. Naujam projektui kilo mintis panaudoti minėtus diodus pašvietimui. Tingėjau rašyti savo programą LED valdymui, tai pažiūrėjau internetuose kaip rekomenduoja STM32 procikui. Ir pirmieji pavyzdukai buvo su taimeriu, PWM ir pertraukimais. Kažkaip griozdiškai viskas atrodė ir dar mano projekte sunaudoti visi PWM signalai.

RGB LED W2812
(fotkė vogta iš interneto, vėliau pakeisiu)

O gal panaudoti tokius:
LEDas
Turiu visą špūlę tik nežinau kas tai.

Kiek paguglinau giliau ir radau elegantišką sprendimą su SPI. Netgi galimas DMA variantas. Man tereikia valdyti tik 6 diodus, tai DMA nenaudosim. Tiesa, po šio sprendimo lieka SPI CLK koja nepanaudojama. O ir pats SPI sunaudojamas. Principas tame, kad reikiamus signalo intervalus suformuojam su keliais bitais baite. Poto užtenka buferį išpumpuoti per SPI ir WS2812 pilnai viską supranta.
Metodas pilnai vogtas iš interneto, todėl va kopyraitas: “© 2008 – 2022 Martin van der Werff · Groningen, The Netherlands.”. Originalaus puslapio adresas: https://www.newinnovations.nl/post/controlling-ws2812-and-ws2812b-using-only-stm32-spi/.

Failiukai, jei nesinori pačiam spausdinti arba jei originalus puslapis dings: WS2812 SPI gcc C.