Rezumatul lucrării [305724]
Rezumatul lucrării
In the following project it is proposed to make a control circuit of an electric system for the control of the roof windows. This project aims to use basic electronic elements and assemblies to prove the possibility of implementing a current control system for the roof windows. Specifically, this project aims to build a smartphone application that transmits wireless commands through a WiFi module to the microcontroller that processes the information and then digitally controls a stepper motor.
The roof windows have been designed to reduce the consumption of energy resources in houses and other buildings. The role of these windows is to light and ventilate rooms that do not have other windows. The roof windows have been designed to reduce the consumption of energy resources in houses and other buildings. The role of these windows is to light and ventilate rooms that do not have other windows.
[anonimizat]. Initially these were controlled by two buttons (open/close), and the communication was done by cable. Currently, the most common way of controlling these windows is by remote control by UV pulses or radio waves. [anonimizat], [anonimizat] a dedicated application.
A very important function to optimize this command line would be adding it a sensor that detects water droplets to automatically close the window at the time in which they were detected.[anonimizat], capacitive sensors or resistive sensors.
A [anonimizat] a [anonimizat]. It provides control of any function in multiple receivers at the same time or only one selected receiver. The system allows control of several receivers ([anonimizat]) via a multi-channel controller (remote control or wall switch). By applying such a solution it is possible to perform simultaneous control of several receivers, e.g. opening 3 windows or lowering blinds in 3 windows) or only one receiver ([anonimizat] a selected window). [anonimizat], smoke detector or wind sensor.
[anonimizat] a wireless communication protocol.
[anonimizat], [anonimizat].
Figura 2. The block diagram
Window Controller is a smartphone application created in Android Studio and aims to transmit appropriate commands to position the window according to user preference. This app can be installed on any device that has the Android operating system.
The window status indicator is a Label that is used to indicate the current position of the SeekBar cursor. [anonimizat] a SeekBar that can be set in 11 states, namely the Close state commanding window closure and states from 10% to 100% with a step of 10% corresponding to the opening angle of the window.
The Connect button is designed to make the connection between the application and Wi-Fi. When pressed it will become invisible. If the connection can not be made, after 5 seconds it will be visible again to retry the connection, and if the connection is successful, the button remains invisible.
The Set Window Status button is intended to transmit to the microcontroller the value indicated by the SeekBar cursor. If the Label indicates the status "Close", then the value 0 followed by the "/" character (47 ASCII) will be sent, and if the Label has another value, the value will be sent to the microcontroller followed by the "/" character (47 ASCII), which activates the interrupt by which the microcontroller receives the data sent by the application.
The microcontroller software operating mode is described in the chart below:
Figura 4. The microcontroller’s chart
On this project, the STM32 Nucleo-F303RE development board was used to process the information, it provides an affordable and flexible way for users to try new concepts and build prototypes, choosing from the various combinations of performance and power consumption features provided by the STM32 microcontroller.
STM32 The NUCLEO-F303RE is a development board based on the ARM Cortex-M4 32 bit RISC high performance microcontroller with FPU operating at 72 MHz and incorporating a floating-point unit (FPU), a unit of Memory Protection (MPU) and an Embedded Trace Macrocell (ETM). They have built-in high-speed memories (512Kbyte flash memory, SRAM 80Kbyte), a static memory (FSAMC) memory controller (SRAM, PSRAM, NOR and NAND) and a wide range of improved and peripheral AHB (Advanced High-performance Bus) and two Advanced Peripheal Bus APBs.
To made the wireless connection between smartphone and microcontroller I used the wi-fi module ESP8266, this is a SOC with integrated TCP / IP protocol that can give it access to the WiFi network of any microcontroller. ESP8266 is capable of hosting an application or take over all Wi-Fi network features from another application processor. This module has a powerful enough processing and storage capability that allows it to be integrated with specific sensors and devices through GPIO pins. ESP8266 supports APSD for VoIP applications and Bluetooth interfaces and contains a self-calibrated RF that allows it to work in all operating conditions and does not require external RF tracks.
The ESP8266 Wi-Fi module is powered from the STM32 Nucleo F303RE development board from the 3.3V power supply. They communicate via the UART communication protocol. The RX pin on the development board was connected to the TX pin from ESP8266, and the TX pin on the debug board was connected to the RX pin from ESP8266.
To retrieve data from the ESP8266 Wi-Fi module, we used an interruption to ensure secure and error-free data transmission. An interrupt handling routine is a function that when the Wi-Fi module transmits information and the character is different from 47 (ASCII) representing the character "/", it is stored in a buffer until the "/" character is transmitted which is the end of the message. After this operation, the variable "set_window" is assigned a value that indicates the position at which the window is intended to be. Finally, after changing the value of the variable, the buffer will be emptied and prepared to record new information.
The Rain Sensor MH-RD is actually a plate that will be exposed to rain. This plate has two strips of conductive material, very close to each other, but without touching. At the moment the water droplets reach the surface, the sensor behaves like a variable resistor, that is, it changes its resistance inversely proportional to the number of rain drops on the plate.
So, if we apply a voltage between the two bands, there will be an open circuit. However, when we expose this surface to rain, falling water closes the circuit between the strips and a different voltage can be measured. When the rain drops fall on the plate, the two bands will not be short-circuited because water is not a perfect conductor. If this sensor acts as a variable resistor, then the resistance will be less when more water falls on the surface, linking the stripes to several points. Sensor resistance varies between 150kΩ and 1MΩ depending on the amount of water deposited on the sensor surface.
This sensor has the advantage of a relatively low production cost, is not subject to abrasion, and is not sensitive to nearby conductive or dielectric objects.
To avoid material damage if the rain starts when the window is open, I have integrated the resistive rain sensor I have described earlier. The operating principle of this sensor in the present paper is as follows: I configured the PA 10 pin as an input pin and I connected a 3.3V pull-up resistor to it and the 3.3V power supply pin. Also, between the pin 10 and GND I connected the rain sensor.
When there are no water droplets on the sensor, the sensor represents an interruption between the input pin and the GND, and at the input the pin will have a logic value of 1. If it does, the signal will be pulled to GND, and the input pin will become 0 logical.
To implement this sensor software, we used a function that is called once at 2ms. If the logic level at input pin PA10 is 0, a second is expected after which the value of the signal is again verified, and if it is 0, then the "raining" variable is assigned the value "1", a value indicating the drops of water on the sensor surface. Otherwise, the variable is given the value "0" representing the absence of water droplets.
A stepper motor is actually an electromechanical device that transforms digital pulses into discrete mechanical motion. Each revolution of the stepper motor is divided into a number of steps, usually 200, and the motor must receive a separate pulse for each step. The stepper motor can take just one step at a time and each step has the same size.
The stepper 28BYJ-48 is one of the most widely used step-by-step motors in prototype applications. This engine is a four-spool unipolar stepper and has 64: 1 speed gearing gears built-in, resulting in an angle of 5.625 ° / step for a complete 360 ° rotation in half-step mode. This means that the engine will have to make 64 steps to complete a rotation and for each step will cover an angle of 5,625 °. However, these motors only work at 5V and therefore can not provide a high torque. In this paper, this engine is used for demonstration purposes only.
The best way to connect a single-pole stepper motor to the microcontroller is by using transistors. ULN2003 contains seven pairs of Darlington TIP120 transistors. The driver can supply up to 500mA on each output and has an internal voltage drop of about 1V when turned on. It also contains internal fly-back diodes to limit peak voltages when inductive loads are ordered. To control the motor, a voltage is applied to each of the coils by following the corresponding sequence.
For these seven pairs of Darlington transistors, the circuit has seven inputs and seven outputs, plus a table pane and a common one. The use of the common pin is optional. It is to be noticed that this circuit has no supply pin (VCC); this is because the voltage required for the operation of the transistors will be provided by the microcontroller.
To control the stepper motor, a function that is called at 100ms is used. If the "raining" variable has a value of 1, it means the rain sensor detected the presence of water splashes, and the variable "set_window" (this value stores the value received from the Window Controller), regardless of the previous value, will get 0 The "window_status" variable indicates the actual window position. If the "set_window" variable is different from the "window_status" variable, then the difference between the two is the number of complete rotations that the engine will perform. Each complete rotation represents 10 percent of the two window limit positions.
At each startup or reset of the microcontroller, an initialization will be performed. Initialization is a function that starts the engine in the sense of closing the window until the switch for detecting the Close state of the window is pressed.
In this project, the STM32 CubeMX program was used to configure the pins and generate the base code. The PC4 and PC5 pins have been configured as UART communication pins and have been connected to the Wi-Fi module. Pins PB1, PB13, PB14, PB15 have been configured as output pin and are used for engine control. Pin PA10 and PC13 were configured as input pin. The PA10 pin is for rain sensor monitoring, and the PC13 pin monitors the state of the switch that causes the window to close.
Planificarea activității
Stadiul actual
Introducere
În următoarea lucrare se propune realizarea unui circuit de comandă al unui sistem electronic pentru controlul ferestrelor de mansardă. Această lucrare are scopul de a utiliza elemente și ansambluri electronice de bază pentru a demonstra posibilitatea de a implementa un sistem actual de control al ferestrelor de mansardă. Mai exact, această lucrare urmărește realizarea unei aplicații pentru smartphone care transmite comenzi wireless prin intermediul unui modul WiFi cărte microcontroler, care prelucrează informația și pe urmă controlează digital un motor pas cu pas.
Generalități
Ferestrele de mansardă au fost proiectate cu scopul de a reduce consumul de resurse energetice din locuințe și alte clădiri. Rolul acestor ferestre este de a lumina si aerisi încăperi care nu dispun de alt tip de ferestre.
Pentru confortul utilizatorilor, dezvoltatorii au proiectat sisteme prin care aceste ferestre să fie acționate de un motor electric. Inițial acestea erau controlate prin intermediul a două butoane (închidere/deschidere), iar comunicarea se efectua prin cablu. În prezent cel mai des întâlnit mod de control al acestor ferestre este prin telecomandă prin impulsuri UV sau unde radio. Pentru că în ultimul deceniu domeniul domoticii a evoluat semnificativ, iar smartphone-urile sunt printre cele mai utilizate dispozitive, cea mai potrivită metodă de control ar fi prin intermediul modulelor de comunicare wireless cum ar fi Wi-Fi sau Bluetooth cu ajutorul unei aplicații dedicate.
O funcție foarte importantă pentru a optimiza acest circuit de comandă ar fi adăugarea
unui senzor care detectează picăturile de apă pentru a închide automat fereastra în momentul
în care acestea au fost detectate.
Există mai multe tipuri de senzori cărora li se pot atribui această funcție, cum ar fi: senzori optici, senzori capacitivi sau senzori rezistivi.
Senzor de ploaie optic
Principiul de funcționare al senzorilor de ploaie optici se poate descrie prin emiterea unui fascicul IR prin sticla de protecție care se va reflecta parțial doar într-un singur punct. Atunci când picăturile de apă apar pe sticlă, unghiul de reflexie se va schimba, iar senzorul va detecta această modificare. Aceasta este o sarcină relativ dificilă, necesitând circuite complexe și fabricate cu mare precizie. Senzorii optici au un cost ridicat de producție și pot produce citiri eronate atunci când murdăria sau alte particule depuse pe sticlă provoacă o reflexie care să imite reflexiile provocate de ploaie. Deoarece se bazează pe un fascicul IR pentru detectare, senzorul optic are, de asemenea, o zona de detectare foarte mică, limitândusi eficacitatea reacției rapide la ploaie. [1]
Senzor de ploaie capacitiv
Senzorul de ploaie capacitiv detectează cu o precizie destul de ridicată densitatea precipitațiilor, intensitatea și sfârșitul acestora cu precizie și eficacitate, evitând semnalele false care pot provoca operații inadecvate (obiecte cum ar fi murdăria sau alte particule care în senzorii optici preexistenți provoacă o reflexie care să imite pe cea a ploii și limitează eficacitatea sa de a răspunde rapid la ploaie ușoară).
Sensibilitatea capacitivă este o tehnologie bazată pe modificarea capacității determinată de modificarea constantei dielectrice a materialului care separă conductorii electrici (plăcile) condensatorului după acțiunea agenților externi.
Sensibilitatea capacitivă devine o tehnologie populară care înlocuiește metodele de detecție optică și modelele mecanice pentru aplicații cum ar fi detectarea proximității/gesturilor, analiza materialelor și detectarea ploii/umidității, deoarece oferă măsurători mai fiabile și mai exacte decât cele optice.
Senzorul are electrozi IDT pe o parte a substratului de aluminiu, în timp ce pe partea opusă se află un încălzitor rezistiv și un senzor de temperatură. Suprafața sensibilă la ploaie, care, în condiții uscate, preia valoarea nominală de 100pF. Mai mult decât atât, în prezența ploii, capacitatea ajunge la valori ridicate în comparație cu condițiile uscate, iar raportul de schimbare este peste 300%.
Încălzitorul integrat și configurabil este prevăzut pentru a se asigura că suprafața de detectare se usucă rapid, protejând suprafața de ceață, umiditatea condensată și îngheț. De asemenea, poate fi dezactivat atunci când consumul de energie este critic.
Substratul de aluminiu și stratul sensibil la sticlă fac senzorul să fie imun la apă și absorbția de umiditate, asigurând rezistență ridicată și durată lungă.
Mai mult, datorită conductivității termice a ceramicii, căldura emisă de încălzitorul din spatele senzorului este imediat transferată pe suprafața superioară, făcând senzorul mai sensibil decât alte tehnologii. [2]
Controler multi-canal
Un sistem foarte utilizat pentru a controla electronic ferestrele de mansardă este acest controler multi-canal care este comandat cu ajutorul unei telecomenzi cu unde radio.
Acesta asigură controlul oricărei funcții pe mai multe receptoare în același timp sau numai un singur receptor selectat. Sistemul permite controlarea mai multor receptoare (de exemplu, ferestre de acoperiș, jaluzele interioare și exterioare) prin intermediul unui controler multi-canal (comandă de la distanță sau întrerupător de perete). Prin aplicarea unei astfel de soluții este posibil să se realizeze controlul simultan al mai multor receptoare, de ex. deschiderea a 3 ferestre sau coborârea jaluzelelor în 3 ferestre) sau doar un singur receptor (de exemplu deschiderea unei ferestre selectate).
Acest sistem poate integra mai multe funcții, cum ar fi senzor de ploaie, detector de fum sau senzor de vânt. [3]
Fundamentare teoretică
Bazele și arhitectura microcontrolerelor ARM
Arhitectura ARM (Advanced RISC Machine) inițial cunoscută sub numele de Acorn RISC Machine, este o arhitectură de microprocesoare de tip RISC (Reduced Instruction Set Computer) 32-bit și 64-bit introduse în 1983 de Acorn Computers și dezvoltate de ARM Holdings începând cu 1990.
Arhitectura ARM a devenit una dintre cele mai utilizate arhitecturi de calculatoare datorită consumului redus de energie, performanței sale ridicate în rezolvarea sarcinilor mici și multiple simultan, a costurilor și a dimensiunilor reduse.
Familia de procesoare Cortex-M este optimizată pentru microcontrolere cu cost redus și eficiență energetică. Aceste procesoare se găsesc într-o varietate de aplicații, incluzând dispozitivele IoT, industriale și dispozitivele de zi cu zi.
Aceste procesoare se bazează pe arhitectura M-Profile care oferă o operație cu o latență redusă și o operație extrem de determinată pentru sistemele embedded. Ultima generație a acestei arhitecturi este Armv8.1-M care include o extensie vectorială numită ARM Helium Technology. Helium aduce îmbunătățiri pentru machine learning și performanță de procesare a semnalului în următorul val de dispozitive embedded, incluzând dispozitive audio, portabile și hub-uri de senzori.
Această familie de procesoare ARM Cortex-M este formată din următoarele modele:
Cortex-M0 este cel mai mic procesor ARM disponibil.
Cortex-M0+ este procesorul ARM care oferă cea mai mare eficiență energetică
Cortex-M1 vizează dispozitivele FPGA. Acest model este conceput pentru a fi accesat instantaneu cu DesignStart FPGA.
Cortex-M3 este cel mai performant procesor pe 32 de biți pentru aplicațiile cele mai determinate în timp real.
Cortex-M4 implementează un amestec bun de control și performanță pentru dispozitivele cu semnal mixt.
Cortex-M7 este cel mai performant membru al familiei de procesoare Cortex-M eficiente din punct de vedere energetic.
Cortex-M23 este microcontrolerul ARM de cea mai mică putere și cel mai mic cu securitate TrustZone.
Cortex-M33 are un amestec ideal de determinare în timp real, eficiență și securitate.
Cortex-M35P: Pentru dezvoltatorii embedded care încearcă să împiedice manipularea fizică și să obțină un nivel mai ridicat de certificare a securității, ARM oferă Cortex-M35P: un procesor robust și performant.
Toate detaliile despre familia de procesoare Cortex-M sunt prezentate in tabelul următor (Figura 15):[4]
Figura 15. Comparația între procesoarele Cortex-M[4]
Arhitectura microcontrolerelor ARM Cortex-M4
Procesorul Cortex-M4 este dezvoltat pentru a aborda piețele de control al semnalului digital care necesită o combinație eficientă și ușor de utilizat a capabilităților de control și de procesare a semnalului. Combinația dintre funcționalitatea de procesare a semnalului de înaltă eficiență și avantajele scăzute, cu costuri reduse și ușurință în utilizare ale procesoarelor Cortex-M este concepută pentru a satisface categoria emergentă de soluții flexibile care vizează în mod specific controlul motorului, industria automotive, sistemele embedded audio și industria automatizării.
Procesorul încorporează trei interfețe de magistrale externe, o interfață ETM care permite conectarea unui ETM(Embedded Trace Macrocell), o interfață AHB Trace Macrocell care permite conectarea simplă a unui ETM la procesor și o interfață Advanced High-performance Bus Access Port (AHB-AP) pentru depanare. [5]
Figura 16. Arhitectura ARM Cortex-M4 – diagrama bloc[5]
STM32 NUCLEO-F303RE
Plăcile de dezvoltare STM32 Nucleo-64 oferă un mod accesibil și flexibil pentru utilizatori de a încerca noi concepte și de a construi prototipuri, alegând din diferitele combinații de caracteristici de performanță și consum de energie furnizate de microcontrolerul STM32.
STM32 NUCLEO-F303RE este o placa de dezvoltare care are la bază microcontrolerul de înaltă performanță ARM Cortex-M4 32 bit RISC, cu FPU care operează la o frecvență de 72 MHz și care încorporează o unitate floating-point(FPU), o unitate de protecție a memoriei (MPU) și un ETM(Embedded Trace Macrocell). Acestea au încorporate memorii de mare viteză (memorie flash 512Kbyte, SRAM 80Kbyte), un controler de memorie flexibil (FSMC) pentru memorii statice (SRAM, PSRAM, NOR și NAND) și o gamă largă de intrări/ieșiri îmbunătățite și periferice conectate la un AHB(Advanced High-performance Bus) și două magistrale APB(Advanced Peripheal Bus).
Această placă de dezvoltare dispune de patru ADC-uri rapide pe 12 biți, șapte comparatoare, patru amplificatoare operaționale, două canale DAC, un RTC cu putere redusă, până la cinci timere de 16 biți cu scop general, un timer de 32 de biți de uz general, și până la trei timere dedicate controlului motorului. Ele oferă, de asemenea, interfețe de comunicare standard și avansate: până la trei I2C-uri, până la patru SPI-uri (două SPI-uri sunt cu I2S-uri multiplexate), trei USART-uri, până la două UART-uri, CAN și USB. Pentru a atinge precizia clasei audio, perifericele I2S pot fi cronometrate cu ajutorul unui PLL extern. STM32 F303E funcționează la temperaturi cuprinse între -40 și + 85 ° C și -40 până la + 105 ° C, de la o sursă de alimentare de la 2,0 la 3,6 V.
Un set cuprinzător de moduri de economisire a energiei permite proiectarea aplicațiilor cu putere redusă. Dispune de 115 intrări / ieșiri rapide care pot fi redate pe vectori de întrerupere externă.
Fiecare dintre pinii GPIO poate fi configurat din software ca ieșire (push-pull sau open-drain), ca și intrare(cu sau fără pull-up sau pull-down) sau ca funcție alternativă periferică. Toți pinii GPIO sunt capabili să suporte un curent ridicat, cu excepția intrărilor analogice. Configurația pentru funcția alternativă I/Os poate fi blocată pentru a evita scrierea falsă a regiștrilor I/Os. [6]
Motorul pas cu pas
Descrierea și modul de funcționare al unui motor pas cu pas
Un motor pas cu pas este de fapt un dispozitiv electromecanic care transformă impulsurile digitale în mișcare mecanică discretă. Fiecare rotație a motorului pas cu pas este împărțită într-un număr de pași, de obicei 200, iar motorul trebuie să primească câte un impuls separat pentru fiecare pas. Motorul pas cu pas poate lua doar un pas la un moment dat și fiecare pas are aceeași dimensiune. Deoarece fiecare impuls determină rotirea motorului cu un unghi precis, de obicei de 1.8°, poziția motorului poate fi controlată fără mecanism de reacție. Pe măsură ce impulsurile digitale cresc în frecvență, mișcarea pașilor se transformă în rotație continuă, viteza de rotație fiind direct proporțională cu frecvența impulsurilor. Motoarele pas sunt utilizate atât în aplicații industriale, cât și comerciale, datorită costului redus, fiabilității ridicate, cuplului ridicat la viteze reduse, dar și datorită construcției simple, robuste care funcționează în aproape orice mediu. [7]
Comparativ cu alte tipuri de motoare electrice (motoare servo, motoare de curent continuu, motoare de curent alternativ, etc), motorul pas cu pas (stepper) prezintă următoarele avantaje:
Unghiul de rotație al motorului este proporțional cu pulsul electric aplicat;
Precizie de poziționare și repetabilitate a mișcării, cu eroare de 3-5% (această eroare nu se cumulează de la un pas la altul);
Răspunsul motoarelor la impulsuri digitale oferă control în buclă deschisă, fapt pentru care motoarele pas cu pas sunt mult mai ușor de controlat;
Răspunsuri rapide la pornire,oprire și schimbarea direcției de rotație;
Posibilitatea de mișcare cu viteză foarte mică, cu sarcină direct pe axul motorului;
Deoarece viteza este proporțională cu frecvența impulsurilor, se obține o gamă largă de viteze de rotație.
Fiabilitate ridicată deoarece nu există perii de contact la motor. Prin urmare, durata de viață a motorului depinde de durata de viață a rulmentului;
Cuplul maxim al motorului este în poziția oprit (în cazul în care înfășurările sunt alimentate);
Categorii de motoare pas cu pas
Motoarele pas cu pas se pot încadra în trei categorii principale:
a) Motoare pas cu pas cu magnet permanent;
b) Motoare pas cu pas hibride.
c) Motoare pas cu pas cu reluctanță variabilă;
a) Motoare pas cu pas cu magnet permanent. La acest tip constructiv înfășurările sunt realizate pe stator, iar rotorul este realizat din magneți permanenți fără dinți, magnetizați perpendicular pe axa care separă polii. Daca bobinele sunt energizate secvențial rotorul se va roti prin atracție magnetică. Aceste motoare realizează mișcari ale axului de 45° sau 90° cu un cuplu ridicat, dar la viteze de rotație mici.
b) Motoare pas cu pas hibride. Sunt o combinație a primelor două tipuri constructive. Funcționează la viteze mari și cuplu dinamic mare. Beneficiază și de așa numitul „detent torque”, adică un cuplu care asigură menținerea fixă a poziției axului și pe durata lipsei energizării bobinelor.
c) Motoare pas cu pas cu reluctanță variabilă. Rotorul este realizat din fier moale și cu înfășurările pe stator. Realizează mișcări de rotație ale axului între 5° și 15° cu o viteză ridicată, dar nu își poate meține poziția axului pe durata lipsei tensiunii de alimentare a bobinelor din care este realizata înfășurarea satorică. [8]
Comparație între motoarele pas cu pas unipolare și bipolare
Driverele unipolare, energizează mereu fazele în același mod. O înfășurare, înfășurarea „comună”, va fi întotdeauna negativă. Celealaltă înfășurare va fi întotdeauna pozitivă. Driverele unipolare pot fi implementate cu circuite simple, cu tranzistoare. Dezavantajul este că oferă un cuplu mai mic, deoarece numai jumătate dintre înfășurări pot fi alimentate la un moment dat.
Driverele bipolare folosesc circuitele în punte pentru a inversa sensul curentului prin faze. Alternând polaritatea curentului prin înfășurări, toate bobinele pot fi puse în funcțiune, ducân la rotirea motorului.
Un motor pas cu pas bipolar în două faze are două grupuri de bobine în timp ce un motor unipolar cu patru faze are patru grupuri de bobine. Un motor bipolar în două faze va avea patru fire, două pentru fiecare fază (Figura 20).
Motor în opt fire (Figura 22). Motorul unipolar în 8 fire este cel mai versatil, deoarece poate fi comandat în mai multe moduri:
Unipolar cu patru faze – toate terminalele comune sunt conectate împreună, asemeni unui motor cu cinci fire;
Bipolar cu două faze în serie – se obtine un curent mai mic consumat de motor deoarece inductanta bobinelor se dubleaza si se obtine un cuplu ridicat la viteze mici.
Bipolar cu două faze în paralel – se obtine un cuplu mai mare la viteze mari, dar in același timp ți curentul prin motor va creste.
Motor în șase fire (Figura 21). La acest motor sunt împerecheate numai terminalele comune a două înfășurări pereche. Aceste două fire pot fi unite pentru a crea un motor unipolar cu cinci fire sau pot fi menținute separate pentru a utiliza motorul ca unul bipolar.
Motor în cinci fire (Figura 23). Acest tip este întâlnit la motoarele unipolare mai mici. Toate terminalele comune sunt legate între ele în interior și sunt scoase în exterior ca al cincilea fir. Acest motor poate fi comandat numai ca un motor unipolar. [9]
Comanda motoarelor pas cu pas
Motoarele pas cu pas unipolare au 5, 6 sau 8 fire. Ele nu au nevoie de un circuit în punte H pentru a fi comandate, în schimb, conform schemei din Figura 24. se poare utiliza un tranzistor pentru fiecare fază și o diodă flyback pentru a preveni apariția vârfurior de tensiune atunci când alimentarea bobinei este oprită.
Există circuite integrate specializate ce au în structura lor toate componenetele necesare petru comanda motoarelor pas cu pas unipolare. În această lucrare se utilizează un cip ULN2003 pentru a comanda motorului pas cu pas 28BYJ-48 cu 5 fire. ULN2003 este un circuit integrat ce are în structura sa șapte perechi Darlington, fiecare pereche fiind capabilă să comande sarcini de până la 50V și 500mA.[10]
Tranzistorul Darlington
Tranzistorul Darlington (uzual, pereche Darlington) este o structură semiconductoare formată din două tranzistoare bipolare (Figura 25) conectate astfel încât curentul amplificat de primul tranzistor este amplificat în continuare de cel de-al doilea. Această configurație oferă un câștig în curent mult mai mare decât fiecare tranzistor luat separat. O pereche Darlington se comportă ca un singur tranzistor, adică are o bază, un colector și un emitor. De obicei, acesta creează un câștig de curent ridicat (aproximativ produsul câștigurilor celor două tranzistoare, datorită faptului că valorile β se multiplică împreună). [11]
O relație generală între câștigul compus și câștigurile individuale este dată de:
βDarlington= β1β2+ β1+ β2 (1)
Dacă 𝛽1 și 𝛽2 sunt suficient de mari (sute), această relație poate fi aproximată la:
βDarlington= β1β2 (2)
Senzorul de ploaie MH-RD
Senzorul de ploaie MH-RD (Figura 26) este de fapt o placă, care va fi expusă ploii. Această placă are două benzi de material conductiv, foarte aproape una de cealaltă, dar fără atingere. În momentul în care picăturile de apă ajung pe suprafața respectivă, senzorul se comportă ca și un rezistor variabil, mai exact acesta își modifica rezistența invers proporțional cu numarul picăturilor de ploaie de pe placă.
Deci, dacă aplicăm o tensiune între cele două benzi, va fi un circuit deschis. Cu toate acestea, atunci când expunem această suprafață la ploaie, apa care cade, închide circuitul între benzi și o tensiune diferită poate fi măsurată.
Atunci când picăturile de ploaie cad pe placă, cele două benzi nu vor fi scurtcircuitate deoarece apa nu este un conductor perfect.
Dacă acest senzor acționează ca un rezistor variabil, atunci rezistența va fi mai mică atunci când mai multă apă cade pe suprafață, legând dungile în mai multe puncte. Rezistența senzorului variază între 150kΩ și 1MΩ în funcție de cantitatea de apă depusă pe suprafața senzorului.
Acest senzor are avantajul unui cost relativ mic de producție, nu este supus abraziunii și nu este sensibil la obiectele conductive sau dielectrice din apropiere.
De asemenea rezistența nu este afectată atunci când există depuneri de murdărie sau alte particule, evitând astfet un semnal eronat. [12]
Keil μVision
Keil μVision este o platformă de dezvoltare software window-based, care combină un editor robust și modern cu un project manager . Acesta integrează toate instrumentele necesare pentru a dezvolta aplicații embedded, inclusiv un compilator C / C ++, un asamblator macro, un linker / locator și un generator de fișiere HEX. μVision ajută la accelerarea procesului de dezvoltare a aplicațiilor încorporate prin furnizarea următoarelor functii:
Editor de cod sursă full-feature.
Device Database pentru configurarea instrumentului de dezvoltare.
Project manager pentru crearea și întreținerea proiectelor.
Funcția Make Utility integrat pentru asamblarea, compilarea și conectarea aplicațiilor embedded.
Interfață GDI avansată pentru depanarea software-ului pe hardware-ul țintă și pentru conectarea la un Adaptor Debug Keil ULINK.
Utilitate de programare Flash pentru descărcarea programului de aplicație în Flash ROM.
IDE-ul și Debugger-ul μVision sunt partea centrală a tool-ului de dezvoltare Keil și au numeroase caracteristici care ajută programatorul să dezvolte rapid și cu succes aplicații embedded.
Instrumentele Keil sunt ușor de utilizat și sunt garantate pentru a vă ajuta să vă atingeți obiectivele de design într-un timp util. μVision oferă un Build Mode pentru crearea de aplicații și un Debug Mode pentru depanarea aplicațiilor. Aplicațiile pot fi depanate cu simulatorul integrat μVision sau direct pe hardware, de exemplu ULINK Debug și Trace Adapters. Dezvoltatorii pot utiliza, de asemenea, alte adaptoare AGDI sau instrumente externe terță parte pentru a analiza aplicațiile.[13]
Android Studio
Android Studio este mediul oficial de dezvoltare integrat (IDE) pentru dezvoltarea aplicațiilor Android. Acesta se bazează pe IntelliJ IDEA, un mediu de dezvoltare integrat Java pentru software și include instrumentele de editare a codului și instrumente de dezvoltare.
Pentru a sprijini dezvoltarea de aplicații în sistemul de operare Android, Android Studio utilizează un sistem de construire bazat pe Gradle, emulator, șabloane de cod și integrare Github. Fiecare proiect din Android Studio are una sau mai multe modalități cu codul sursă și fișierele de resurse. Aceste modalități includ module de aplicații Android, module de bibliotecă și module Google App Engine.
Android Studio folosește o caracteristică Instant Push pentru a împinge modificările de cod și resurse la o aplicație în desfășurare. Un editor de cod ajută dezvoltatorul cu scrierea codului și oferind completarea codului, refracția și analiza. Aplicațiile construite în Android Studio sunt apoi compilate în format APK pentru a fi trimise la Magazin Google Play. Android Studio vă permite să instalați pluginuri pentru aproape orice scop. Multe dintre ele sunt destul de specifice, dar aici este o mică selecție care vă va accelera în task-urile zilnice.
Software-ul a fost anunțat pentru prima oară la Google I/O în mai 2013, iar prima construcție stabilă a fost lansată în decembrie 2014. Android Studio este disponibil pentru platforme desktop Mac, Windows și Linux. Acesta a înlocuit Eclipse Android Development Tools (ADT) ca IDE primar pentru dezvoltarea de aplicații Android. [14]
STM32CubeMX
STM32CubeMX este un instrument grafic care permite o configurare foarte ușoară a microcontrolerelor și microprocesoarelor STM32, precum și generarea codului C de inițiere corespunzător pentru nucleul Arm Cortex-M sau un arbore de dispozitiv Linux parțial pentru Arm Cortex-A), printr-un proces pas cu pas.
Primul pas constă în selectarea microcontrolerului STM32 STM32 sau a microprocesorului care se potrivește cu setul necesar de periferice.
Pentru microprocesoare, al doilea pas permite configurarea GPIO-urilor și configurarea ceasurilor pentru întregul sistem și atribuirea interactivă a perifericelor fie Arm Cortex-M, fie grupului Cortex A. Specificațiile precum ar fi configurarea și reglarea DDR, facilitează pornirea cu microprocesoarele STM32. Pentru nucleul Cortex-M, configurația include pași suplimentari care sunt exact asemănători cu cei descriși pentru microcontrolere.
Pentru microcontrolere și microprocesor Arm Cortex-M, al doilea pas constă în configurarea fiecărui software embedded, datorită unui pinout-conflict solver, a unui ajutor de setare a ceasului, a unui calculator de consum de energie și a unei funcții care configurează perifericele cum ar fi GPIO sau USART) și stivele middleware (cum ar fi USB sau TCP / IP).
În cele din urmă, utilizatorul lansează generația care se potrivește cu alegerile de configurație selectate. Acest pas oferă codul C de inițiere pentru Arm Cortex-M, gata pentru a fi utilizat în mai multe medii de dezvoltare sau un arbore al dispozitivului parțial Linux pentru Arm Cortex-A. [15]
Modulul Wi-Fi ESP8266
Modulul WiFi ESP8266 este un SOC cu protocol TCP / IP integrat care îi poate da acces la rețeaua WiFi oricărui microcontroler. ESP8266 este capabil de hosting pentru o aplicație sau să preia toate funcțiile de rețea Wi-Fi de la un alt procesor de aplicație. Fiecare modul vine pre-programat, cu firmware cu comenzi AT.
Acest modul are o capacitate de procesare și stocare suficient de puternică, care îi permite să fie integrat cu senzori și dispozitive specifice prin intermediul pinilor GPIO. ESP8266 suportă APSD pentru aplicații VoIP si interfețe cu Bluetooth și contine un RF auto-calibrat care îi permite sa lucreze in toate conditiile de functionare și nu necesită piese RF externe.
ESP8266 este capabil să funcționeze consecvent în medii industriale, datorită domeniului larg al temperaturii de funcționare. Cu caracteristici integrate pe chip și număr minim de componente discrete externe, cipul oferă fiabilitate, compactitate și robustețe.
ESP8266 este integrat cu un procesor Tensilica pe 32 de biți, interfețe digitale periferice standard, întrerupătoare de antenă, amplificator de putere, amplificator de zgomot redus, filtre și module de gestionare a alimentării.
Proiectat pentru dispozitive mobile, electronice portabile și aplicații IoT, ESP8266 realizează un consum redus de energie, combinând mai multe tehnologii brevetate. Arhitectura de economisire a energiei dispune de trei moduri de funcționare: modul activ, modul somn și modul de adormire profundă. Acest lucru permite dispozitivelor alimentate de baterii să funcționeze mai mult timp. [16]
Protocolul de comunicare Telnet
Protocolul de comunicare Telnet oferă o modalitate de a vă conecta de la distanță la un alt dispozitiv, ca și cum ați fi așezat în fața acestuia și să îl utilizați ca orice alt computer. În zilele noastre, Telnet poate fi folosit de la un terminal virtual sau dintr-un emulator terminal, care este, în esență, un calculator modern care comunică cu același protocol Telnet.
Un exemplu este comanda Telnet, disponibilă din Promptul de comandă din Windows. Comanda telnet, fără îndoială, este o comandă care utilizează protocolul Telnet pentru a comunica cu un dispozitiv sau sistem la distanță. Comenzile Telnet pot fi executate și pe alte sisteme de operare, cum ar fi Linux, Mac și Unix, mult în același mod ca în Windows.
Telnet nu este același lucru ca și alte protocoale TCP / IP precum HTTP, care vă permit să transferați fișiere către și de la un server. În schimb, protocolul Telnet este conectat la un server ca și cum ați fi un utilizator real, oferindu-vă un control direct și toate aceleași drepturi la fișiere și aplicații ca și utilizatorul în care sunteți conectat. [28]
Implementarea soluției adoptate
Descrierea funcțională după schema bloc
După cum s-a prezentat la începutul acestei lucrări, acest proiect urmărește realizarea circuitului de comandă pentru controlul electronic al unei ferestre de mansardă prin utilizarea unui protocol de comunicare wireless.
Schema bloc a circuitului este formată din două părți, mai exact, prima parte are rolul de a prelua comenzile de la utilizator, iar a doua parte are ca scop controlul actuatorului.
Figura 31. Schema bloc
Aplicația Window Controller
Window Controller este o aplicație pentru smartphone creată în programul Android Studio și are ca scop transmiterea comenzilor corespunzătoare pentru a poziționa fereastra conform preferinței utilizatorului. Această aplicație se poate instala pe orice dispozitiv care rulează sistemul de operare Android.
Figura 32. Interfața aplicației Window Controller
Descrierea funcțională
Indicatorul statusului ferestrei este un Label care este folosit pentru a indica poziția actuală a cursorului de la SeekBar.
Pentru a selecta poziția dorită pentru fereastră am adăugat un SeekBar care poate fi setat în 11 stări, mai exact starea Close care comandă închiderea ferestrei și stările de la 10% până la 100% cu un pas de 10 procente, corespunzătoare unghiului de deschidere al ferestrei. SeekBar-ul a fost configurat cu 101 puncte, adică de la 0 la 100. Când cursorul se află în intervalul (0-5], starea va fi Close, dacă poziția cursorului este în intervalul (5-10) statusul va fi 10, iar dacă poziția cursorului se află între două numere care sunt multiplii ai numărului 10, valoarea statusului va fi rotunjită în jos.
Figura 33. Funcția care stabilește valoarea returnată de SeekBar
Butonul Connect are rolul de a efectua conexiunea între aplicație si Wi-Fi. Atunci când este apăsat va deveni invizibil. Dacă nu se poate efectua conexiunea, după 5 secunde va fi din nou vizibil pentru a reîncerca conectarea, iar în cazul în care conexiunea se realizează cu succes, butonul rămâne invizivil. Funcția respectivă este prezentată în Figura 34.
Butonul Set Window Status are rolul de a transmite către microcontroler valoarea indicată de către cursorul SeekBar-ului. Daca Label-ul indică starea “Close”, atunci se va trimite valoarea 0 urmată de caracterul “ / ”(47 ASCII), iar dacă Label-ul are altă valoare, se va trimite către microcontroler valoarea respectivă urmată de caracterul “ / ”(47 ASCII), care activează întreruperea prin care microcontrolerul recepționează datele trimise de aplicație.
Organigrama programului
Pentru ca microcontrolerul să funcționeze corespunzător, codul încărcat a fost scris urmând cuatenție logica descrisă în Figura 36.
Figura 36. Organigrama programului pentru microcontroler
Modulul Wi-Fi ESP8266
Modulul de comunicație wireless ESP 8266 este utilizat pentru a realiza comunicația fără fir între smartphone și circuitul de comandă al actuatorului.
Caracteristici hardware:
Wi-Fi Direct (P2P), soft-AP
Protocol TCP / IP integrat
802.11 b / g / n
Comutator TR, balun, LNA si amplificator de putere integrate
PLL, DCXO, regulatoare si unitati de gestionare a energiei integrate
+19.5dBm putere iesire in modul 802.11b
Memorie flash 1MB
CPU-ul integrat de 32 bit cu consum redus de energie ar putea fi folosit ca procesor de aplicare
SDIO 1.1 / 2.0, SPI, UART
STBC, 1×1 MIMO, 2×1 MIMO
A-MPDU & A-MSDU aggregation & 0.4ms guard interval
Transmite pachete in < 2 ms
Consumul de energie in modul standby de < 1.0mW (DTIM3) [17]
Configurația pinilor:
VCC: Pin de alimentare 3.3V.
GND: Pin de masa.
EN(Enable): Când acest pin are statusul Low, modulul este dezactivat, rezultând un consum redus de curent, iar comunicația este inexistentă. Cand are statusul High, modulul este activ si se efectueaza comunicația.
TX si RX: Sunt pinii de transmitere și recepție pentru protocolul de comunicare UART.
RST(Reset): Pin pentru resetare externă. Cand are statusul Low are loc resetarea.
GPIO0 (Flash): Dacă acest pin are statusul Low la pornirea alimentării sau resetare, acesta este transferat în modul de programare serială. [18]
Firmware pentru ESP8266
Acest modul Wi-Fi are preinstalat un firmware care folosește un protocol cu comenzi AT pentru a efectua comunicația.Pentru a transmite mesaje din aplicația Window Controller, am încărcat firmware-ul esp-link v2.1.7 care folosește un protocol de comunicare cu comenzi telnet. [19]
Conexiunea dintre ESP8266 și microcontroler
Modulul Wi-Fi ESP8266 este alimentat de la placa de dezvoltare STM32 Nucleo F303RE de la pinul de alimentare de 3.3V. Acestea comunica prin intermediul protocolului de comunicare UART. Pinul RX de la placa de dezvoltare a fost conectat la pinul TX de la ESP8266, iar pinul TX de la placa de dezvlotare a fost conectat la pinul RX de la ESP8266 (Figura 38).
Figura 38. Schema de conectare dintre ESP8266 si STM32 Nucleo
UART (Universal Asynchronous Receiver-Transmitter) nu este un protocol de comunicare cum ar fi SPI și I2C, ci un circuit fizic într-un microcontroler sau un stand-alone IC. Scopul principal al protocolului de comunicare UART este de a transmite și primi date seriale.
În comunicația UART, două dispozitive comunică direct unul cu celălalt. UART-ul de transmisie convertește datele paralele dintr-un dispozitiv de control ca un procesor în format serial, îl transmite serial către UART-ul receptor, care apoi convertește datele seriale înapoi în date paralele pentru dispozitivul receptor. Doar două fire sunt necesare pentru a transmite date între două UART-uri.
Linia de transmisie a datelor UART este în mod normal menținută în nivelul HIGH atunci când nu transmite date. Pentru a începe transferul de date, UART-ul de transmisie își schimbă starea din HIGH in Low pentru un ciclu de ceas. Când UART-ul de recepție detectează tranziția din High în Low, începe să citească biții din cadrul de date la frecvența ratei de transmisie.
Cadrul de date conține datele efective transferate. Poate fi de la 5 biți până la 8 biți dacă este folosit un bit de paritate. Dacă nu este utilizat un bit de paritate, cadrul de date poate avea lungimea de 9 biți. În cele mai multe cazuri, datele sunt trimise mai întâi cu bitul cel mai puțin semnificativ.
Bitul de paritate este o modalitate pentru UART-ul de recepție pentru a afla dacă s-au schimbat date în timpul transmisiei. Biții pot fi modificați prin radiații electromagnetice, rate de transmisie necorespunzătoare sau transferuri de date la distanță. După ce UART-ul recepționează citirea cadrului de date, acesta numără numărul de biți cu o valoare de 1 și verifică dacă numărul total este un număr par sau impar. Pentru a semnala sfârșitul pachetului de date, UART-ul de trimitere acționează linia de transmisie de date de la nivelul Low la nivelul High pentru cel puțin două perioade de clock. [20]
Preluarea datelor de la ESP8266
Pentru a prelua datele de la modulul Wi-Fi ESP8266 am folosit o întrerupere pentru a asigura o transmisie de date sigură și fără erori.
Rutina de tratare a întreruperii este o funcție care, atunci când modulul Wi-Fi transmite informații, iar caracterul este diferit de 47(ASCII) care reprezintă caracterul “/”, acesta este stocat într-un buffer până când se transmite caracterul “/” care reprezintă finalul mesajului. După această operațiune, variabilei “set_window” i se atribuie o valoare care semnifică poziția la care se dorește să fie fereastra.
În final, după ce am modificat valoarea variabilei, bufferul va fi golit și pregătit pentru a înregistra noi informații. Această funcție este prezentată în Figura 39.
Figura 39. Funcția pentru recepționarea datelor
Senzorul de ploaie MH-RD
Pentru a evita apariția unor daune materiale în cazul în care începe ploaia atunci când fereastra este deschisă, am integrat senzorul de ploaie rezistiv pe care l-am descris anterior.
Principiul de funcționare al acestui senzor în lucrarea de față este următorul: (Figura 40)
Am configurat pinul PA 10 ca pin de intrare și am conectat între acesta și pinul de alimentare de 3.3V un rezistor de pull-up de 1MΩ. Tot între pinul PA 10 și GND am conectat senzorul de ploaie.
Atunci când pe senzor picăturile de apă sunt inexistente, senzorul reprezintă o întrerupere între pinul de intrare și GND, iar la intrare pinul va avea valoarea 1 logic. În caz contar, semnalul va fi tras la GND, iar valoarea pinului de intrare va deveni 0 logic.
Figura 40. Schema de conectare dintre senzorul de ploaie și STM32 Nucleo
Pentru a implementa software acest senzor, am folosit o funcție care este apelată o dată la 2ms. Dacă nivelul logic la pinul de intrare PA10 este 0, se așteaptă o secundă dupa care se verifică încă o dată valoarea semnalului, iar dacă este tot 0, atunci variabilei “raining” i se atribuie valoarea “1’, valoare ce indică existența picăturilor de apă pe suprafața senzorului. În caz contrar, variabila primește valoarea “0”, reprezentând absența picăturilor de apă. Funcția responsabilă cu algoritmul pentru detectarea apariției picăturilor de apă este prezentată în Figura 41.
Figura 41. Funcția pentru senzorul de ploaie
Motorul pas cu pas 28BYJ-48
Configurația motorului 28BYJ-48
Motorul 28BYJ-48 este unul din cele mai utilizate motoare pas cu pas în aplicațiile care se află în stadiul de prototip. Acest motor este un stepper unipolar cu patru bobine (Figura 42) și are pinioane reductoare de viteză încorporate în raport de 64:1, astfel că rezultă un unghi de 5.625°/pas pentru o rotație complteta de 360° în modul half-step. Asta înseamnă că motorul va trebui să facă 64 de pași pentru a finaliza o rotație și pentru fiecare pas va acoperi un unghi de 5.625°. Cu toate acestea, aceste motoare funcționează doar la tensiunea de 5V și, prin urmare, nu pot furniza un cuplu ridicat. În lucrarea de față se utilizează acest motor doar în scop demonstrativ. [21]
Figura 42. Motorul 28BYJ-48
Motorul are patru înfășurări bobinate care trebuie alimentate într-o anumită secvență pentru a roti axul magnetic al motorului. Când se folosește metoda de comandă full-step, două din cele patru bobine sunt alimentate la fiecare pas(Tabelul 1). În lucrarea de față, pentru a efectua deschiderea ferestrei am folosit acest mod, iar pentru a efectua închiderea ferestrei am folosit modul respectiv, dar în sens opus. [22]
Tabelul 1. Ordinea de comandă in modul Full-Step
Specificațiile tehnice ale motorului
Tensiunea de alimentare: 5V DC
Număr faze: 4
Unghi de rotație: 5.625°/64 (half-step) sau 11.25°/32 (full-step)
Raport reducție: 64:1
Cuplu minim: 34.3 mN*m
Grad de izolație: A
Rezistență/fază: 50ohm
Înfășurare: unipolar cu 5 înfățurări
Frecvența: 100Hz
Greutate:30g [23]
Driverul ULN2003
Cea mai potrivită modalitate de a conecta un motor pas cu pas unipolar cu microcontrolerul este folosirea unor tranzistoare. ULN2003 conține șapte perechi de tranzistoare Darlington TIP120. Driverul poate furniza pe fiecare ieșire un curent de până la 500mA și are o cădere de tensiune internă de aproximativ 1V atunci când este pornit. De asemenea, conține diode fly-back interne pentru a limita vârfurile de tensiune atunci când sunt comandate sarcini inductive. Pentru a controla motorul se aplică o tensiune pe fiecare dintre bobine respectând secvența descrisă în Tabelul 1.
Pentru aceste șapte perechi de tranzistoare Darlington circuitul dispune de șapte intrări și șapte ieșiri, la care se adaugă un pin de masă și unul comun. Folosirea pinului comun este opțională. De observat este că acest circuit nu are pin de alimentare (VCC); acest lucru se datorează faptului că tensiunea necesară pentru funcționarea tranzistoarelor va fi furnizată de microcontroler. Sarcinile conectate la ieșire pot fi de maxim de 50V și 500mA fiecare. Cu toate acestea, se pot comanda sarcini mai mari combinând doi sau mai mulți pini de ieșire. De exemplu, dacă se combină trei pini se poate furniza un curent de până la (3*500mA) ~ 1.5A. Intrările sunt compatibile cu logica TTL sau 5V CMOS.
În Figura 43 este prezentat driverul ULN2003. Acesta oferă o interfață directă între microcontroler și motor. Modulul dispune de patru intrări pentru conectarea microcontrolerului, pini pentru conexiunea la sursa de alimentare a motorului pas cu pas, jumper ON/OFF, patru LED-uri pentru a indica semnalele de comandă și patru pini pentru conectarea motorului. [24]
Conexiunea dintre ULN2003 și microcontroler
Pentru a transmite comenzi de la microcontroler la driverul ULN2003, pinii GPIOB 1, 13, 14, 15 au fost configurați ca output pin și au fost conectați la intrările digitale IN1, IN2, IN3 și IN4 ale driverului. (Figura 45)
Figura 45. Conexiunea dintre microcontroler, driver și motor
Implementarea software
Pentru a controla motorul pas cu pas se folosește o funcție care se apelează la un interval de 100ms.
Dacă variabila “raining” are valoarea 1, înseamnă că senzorul de ploaie a detectat prezența stropilor de apă, iar variabila “set_window” (în această variabilă este stocată valoarea primită de la aplicația Window Controller), indiferent de valoarea anterioară, va primi valoarea 0. Variabila “window_status” indică poziția actuală a ferestrei. Dacă variabila “set_window” este diferită de variabila “window_status”, atunci diferența dintre cele două reprezintă numărul de rotații complete pe care le va efectua motorul. Fiecare rotație completă reprezintă 10 procente dintre cele două poziții limită ale ferestrei.
În Figura 47 sunt prezentate cele două funcțiile pentru deschiderea respectiv închiderea ferestrei. În modul full-step, pentru o rotație completă sunt necesare 512 repetări.
Figura 47. Funcțiile pentru deschiderea/închiderea ferestrei
Inițializarea
La fiecare pornire sau resetare a microcontrolerului, se va efectua o inițializare. Inițializarea este o funcție care pornește motorul în sensul închiderii ferestrei până în momentul în care este apăsat switch-ul responsabil pentru detectarea stării Close a ferestrei.
În Figura 48 este prezentată conexiunea dintre microcontroler si switch-ul care este responsabil pentru detectarea stării Close a ferestrei. Am configurat pinul PC13 ca pin de intrare și am conectat între acesta și pinul de alimentare de 3.3V un rezistor de pull-up de 1MΩ. Tot între pinul PC13 și GND am conectat un switch care, atunci când nu este apăsat, la intrare pinul va avea valoarea 1 logic. În caz contar, semnalul va fi tras la GND, iar valoarea pinului de intrare va deveni 0 logic.
Configurarea pinilor
În lucrarea de față s-a utilizat programul STM32 CubeMX pentru configurarea pinilor și generarea codului de bază(Figura 49). Pinii PC4 si PC5 au fost configurați ca pini de comunicare UART și au fost conectați la modulul Wi-Fi. Pinii PB1, PB13, PB14, PB15 au fost configurați ca output pin și sunt utilizați pentru comanda motorului. Pinul PA10 și PC13 au fost configurați ca input pin. Pinul PA10 este utilizat pentru monitorizarea senzorului de ploaie, iar pinul PC13 monitorizează starea switch-ului care determină închiderea ferestrei.
Rezultate experimentale
Funcționalitatea acestui sistem și a componentelor utilizate au fost testate și verificate cu echipamente de laborator (osciloscop, multimetru, sursă de precizie și probă de curent).
Transmisia datelor prin UART
În Figura 50 a fost capturată secvența în care datele recepționate de către modulul Wi-Fi de la aplicația Window Controller și le transmite către microcontroler prin intermediul protocolului de comunicare UART. Pe canalul 1 este reprezentat pinul TX de la microcontroler, iar pe canalul 2 este afișat pinul RX de la microcontroler.
Figura 50. Transmisia datelor prin UART
Comanda driverului ULN2003
În Figura 51 sunt prezentate semnalele de intrare ale driverului pentru motorul pas cu pas pentru sensul de deschidere al ferestrei. Se poate observa că logica semnalelor este aceeasi ca și în Tabelul 2.
Tabelul 2. Ordinea de comandă in modul Full-Step
Figura 51. Semnalele de intrare ale driverului
În Figura 52 sunt prezentate semnalele de intrare ale driverului pentru sensul de închidere al ferestrei. Se poate observa că logica semnalelor este în sens invers față de Figura 51.
Figura 52. Semnalele de intrare ale driverului
Semnalele de ieșire ale driverului pentru motorul pas cu pas sunt prezentate în oscilogramele de mai jos. În Figura 53 se pot vedea cele patru ieșiri ale driverului pentru sensul de deschidere a ferestrei. Se poate observa că logica semnalelor corespunde cu logica semnalelor de intrare, singura diferență fiind amplitudinea lor.
Figura 53. Semnalele de iesire ale driverului
În Figura 54 sunt afișate semnalele de ieșire ale driverului pentru sensul de închidere a ferestrei. La fel ca și în oscilograma anterioară, logica semnalelor de ieșire este identică, cu cea a semnalelor de intrare.
Figura 54. Semnalele de iesire ale driverului
Frecvența semnalelor de intrare și ieșire
În oscilogramele de mai jos se poate observa că frecvența dintre semnalele de intrare și semnalele de ieșire este aceeași, însă diferă amplitudinea acestora.
Figura 55. Frecvența semnalelor de intrare
Figura 56. Frecvența semnalelor de ieșire
Semnalele de ieșire pot fi vizualizate și cu ajutorul LED-urilor de pe PCB-ul driverului.
LED-urile se vor aprinde numai dacă ieșirile driverului sunt pe nivel Low. Spike-urile de tensiune de pe semnalele de iesire apar din cauza sarcinii inductive a motorului și a consumului relativ ridicat de curent al motorului sub sarcină.
Figura 57. Preluarea semnalelor de ieșire
În oscilograma de mai jos (Figura 58) se poate observa că atunci când semnalul de intrare este în starea High, ieșirea corespunzătoare este activată.
Figura 58. Semnalul de intrare și semnalul de ieșire
Consumul de curent
După cum se poate observa în Figura 59 întregul sistem are un consum de curent de aproximativ 340mA atunci când motorul este în funcțiune.
Figura 59. Consumul de curent total
Atunci când sistemul este în stand-by are un consum de aproximativ 440mA.
Figura 60. Consumul de curent total în stand-by
În Figura 61 se poate observa că motorul are un consum de aproximativ 187mA atunci când este în funcțiune.
Figura 61. Consumul de curent al motorului
Consumul individual de curent al microcontrolerului atunci când motorul și modulul Wi-Fi sunt deconectate este de aproximativ 70mA.
Modulul Wi-Fi ESP8266, după cum se poate vedea și în Figura 63 are un consum individual de curent de aproximativ 70mA.
Figura 63. Consumul de curent al modulului Wi-Fi
În oscilograma următoare(Figura 64) a fost surprins intervalul de tip dintre momentul în care este apăsat switch-ul și sfârșitul comenzii pentru închiderea ferestrei. Acest interval este de aproximativ 1 ms.
Figura 64
Concluzii
Un lucru important de menționat este că lucrarea de față reprezintă doar baza unui prototip și a fost realizată strict în scop demonstrativ. Pentru că în zilele de astăzi aproape fiecare persoană deține un smartphone, prin realizarea acestui prototip s-a încercat conturarea unei idei prin care soluțiile propuse și utilizate pot duce către crearea cu succes al unui sistem de control de actualitate al ferestrelor de mansardă.
Rezultatele experimentale prezentate la sfârșitul acestei lucrări sunt de asemenea demonstrative, întrucât puterea motorului prezentat este de departe insuficientă ca să acționeze o fereastră. Pentru a putea controla o fereastră, pe lângă sistemul prezentat, mai este nevoie și de un sistem mecanic complex cu pinioane.
Acest sistem poate fi îmbunătățit adăugând anumiți senzori, astfel încât să îndeplinească mai multe funcții, precum un senzor de oxigen ca să deschidă fereastra atunci când nivelul este prea scăzut, senzor de gaz pentru a evita posibilitatea de producere a unei explozii,un senzor de vânt care să fie montat pe acoperiș pentru a menține fereastra închisă atunci când viteza vântului este prea ridicată, senzor de poziție, un ampermetru care să comunice cu microcontrolerul, iar atunci când curentul depășește limita maximă să întrerupă operațiunea de închidere/deschidere deoarece fereastra ar putea fi blocată și senzori de temperatură.
De asemenea acestui sistem i s-ar putea atribui mai multe funcții, precum controlul unei usi de garaj, controlul jaluzelelor de exterior, al unei porți de intrare, sau orice sistem care are nevoie de mișcare de rotație.
Aplicația Window Controller poate fi mult îmbunătățită implementând și funcția de primire a datelor de la microcontroler, precum informații de la senzorii menționați anterior, eventuale notificări pentru cazuri ugente, sau anumite moduri de funcționare care au la bază informațiile preluate de la senzori, care să fie selectate după preferințele utilizatorului.
În cele din urmă, prin crearea acestui prototip numit Sistem și aplicație pentru controlul inteligent al ferestrelor, s-a demonstrat posibilitatea de a integra aceste sisteme electronice de comandă și comunicații wireless în structura componentelor mecanice pentru controlul unei ferestre de mansardă.
Bibliografie
[1] Arun KUNDGOL, ”A novel technique for measuring and sensing rain”, 2015
[2] Telecontrolli, https://www.electronicspecifier.com/sensors/ceramic-capacitive-rain-sensor-avoids-false-positives, 2016
[3] Farko, https://www.fakro.co.uk/products/all-products/electric-control/multi-channel-control/
[4] ARM Cortex-M processors, https://developer.arm.com/ip-products/processors/cortex-m
[5] ARM Cortex-M4 processor, https://developer.arm.com/products/processors/cortex-m/cortex-m4
[6] “STM32 NucleoF303RE datasheet”
[7] Stepper Motors, https://circuitdigest.com/tutorial/what-is-stepper-motor-and-how-it-works
[8] Tarun, Agarwal, "Stepper Motor – Types, Advantages & Applications"
[9] Type of stepper motors, https://www.brighthubengineering.com/diy-electronics-devices/109665-operating-principle-of-stepper-motors-explained/
[10] Introduction to ULN2003, https://www.theengineeringprojects.com/2017/06/introduction-to-uln2003.html
[11] Darlingron transistor working, https://www.elprocus.com/darlington-transistor-working-with-applications/
[12] Rain sensor module, https://www.openhacks.com/uploadsproductos/rain_sensor_module.pdf
[13] About μVision, http://www.keil.com/support/man/docs/uv4/uv4_overview.htm
[14] Android Studio, https://searchmobilecomputing.techtarget.com/definition/Android-Studio
[15] STM32CubeMX overview, https://www.st.com/en/development-tools/stm32cubemx.html
[16] ESP8266 WiFi, https://www.robofun.ro/wifi-module-esp8266
[17] ESP8266EX, https://www.espressif.com/en/products/hardware/esp8266ex/overview
[18] ESP8266 Pin Configuration, https://components101.com/wireless/esp8266-pinout-configuration-features-datasheet
[19] esp-link, https://github.com/jeelabs/esp-link
[20] Basics of UART Communication, http://www.circuitbasics.com/basics-uart-communication/
[21] 28BYJ-48 – 5V Stepper Motor, https://components101.com/motors/28byj-48-stepper-motor
[22] 28BYJ-48- full step, https://42bots.com/tutorials/28byj-48-stepper-motor-with-uln2003-driver-and-arduino-uno/
[23] "28BYJ-48 data sheet"
[24] "ULN2003 data sheet", STMicroelectronics
[25] "μVision help"
[26] "STM32CubeMX help"
[27] "Android Studio help"
[28] How to use the Telnet Client, https://www.lifewire.com/what-is-telnet-2626026
Anexe
Codul sursă al microcontrolerului
#include "main.h"
#include "stm32f3xx_hal.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private variables –––––––––––––––––––*/
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
/* Private variables –––––––––––––––––––*/
extern volatile unsigned int ms;
uint8_t rx_index = 0;
uint8_t rx_data;
uint8_t rx_buffer[3];
unsigned int window_status ;
unsigned int set_window;
unsigned int raining;
/* USER CODE END PV */
/* Private function prototypes ––––––––––––––––*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_NVIC_Init(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes ––––––––––––––––*/
void initialization(void);
void task_100ms(void);
void rain_sensor(void);
void open_window(void);
void close_window(void);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
*
* @retval None
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration–––––––––––––––––––-*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* Initialize interrupts */
MX_NVIC_Init();
/* USER CODE BEGIN 2 */
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);//enable receive interrupt
HAL_UART_Receive_IT(&huart1,&rx_data,1);
initialization();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(!(ms%100))
task_100ms();
if(!(ms%2000))
rain_sensor ();
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/**
* @brief NVIC Configuration.
* @retval None
*/
static void MX_NVIC_Init(void)
{
/* USART1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* PVD_IRQn interrupt configuration */
HAL_NVIC_SetPriority(PVD_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(PVD_IRQn);
/* FLASH_IRQn interrupt configuration */
HAL_NVIC_SetPriority(FLASH_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(FLASH_IRQn);
/* RCC_IRQn interrupt configuration */
HAL_NVIC_SetPriority(RCC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(RCC_IRQn);
/* FPU_IRQn interrupt configuration */
HAL_NVIC_SetPriority(FPU_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(FPU_IRQn);
}
/* USART1 init function */
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
/*Configure GPIO pin : PC13 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : PB1 PB13 PB14 PB15 */
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : PA10 */
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
if(huart->Instance == USART1){
if(rx_index==0){ //golire buffer
for(int i=0;i<3;i++)
rx_buffer[i]=0;
}
if(rx_data!=47){ //daca, caracterul receptionat este altul decat "/",
rx_buffer[rx_index++]=rx_data; //acesta este stocat in buffer
}
else{
if(rx_index == 1)//daca se receptioneaza un singur caracter, acesta este 0
set_window = 0;
if(rx_index == 2)
set_window = (rx_buffer[0] – '0');//conversia string to int
if(rx_index == 3) //daca se receptioneaza 3 caractere, valoarea este 100
set_window = 10;
rx_index=0;
}
HAL_UART_Receive_IT(&huart1,&rx_data,1);
}
}//end interrupt function
void task_100ms(){
if(raining == 1)
set_window = 0;
if(set_window != window_status){
if(set_window > window_status){
open_window();
}
else{
close_window();
}
}
}//end task_100ms
void rain_sensor(){
if(HAL_GPIO_ReadPin( GPIOA ,GPIO_PIN_10 ) == 0){
HAL_Delay(1000);
if(HAL_GPIO_ReadPin( GPIOA ,GPIO_PIN_10 ) == 0){
raining = 1;
}
}
else
raining = 0;
}//end rain_sensor
void open_window(){
for(int step=0;step < 512;step++){
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_RESET);
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_RESET);
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_SET);
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_SET);
HAL_Delay(1);
}
window_status++;
HAL_Delay(100);
}//end open_window
void close_window(){
for(int step=0;step < 512;step++){
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_SET);
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_SET);
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_RESET);
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_RESET);
HAL_Delay(1);
}
window_status–;
HAL_Delay(100);
}//end close_window
void initialization(){
while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13)){
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_SET);
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_SET);
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_RESET);
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_RESET);
HAL_Delay(1);
}
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13, GPIO_PIN_RESET);
}//end initialization
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @param file: The file name as string.
* @param line: The line in file as a number.
* @retval None
*/
void _Error_Handler(char *file, int line)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
while(1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
Codul sursă al aplicației Window Controller
package com.example.cosmincodrea.license;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
public class MainActivity extends Activity implements SeekBar.OnSeekBarChangeListener {
Button btnStart, btnSend;
TextView statusProgres;
SeekBar seekbar;
NetworkTask networktask;
int progress;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart = (Button) findViewById(R.id.btnStart);
btnSend = (Button) findViewById(R.id.btnSend);
statusProgres = findViewById(R.id.value);
seekbar = findViewById(R.id.seekBar);
btnStart.setOnClickListener(btnStartListener);
btnSend.setOnClickListener(btnSendListener);
seekbar.setOnSeekBarChangeListener(this);
networktask = new NetworkTask(); //Create initial instance so SendDataToNetwork doesn't throw an error.
}
private OnClickListener btnStartListener = new OnClickListener() {
public void onClick(View v) {
btnStart.setVisibility(View.INVISIBLE);
networktask = new NetworkTask(); //New instance of NetworkTask
networktask.execute();
}
};
private OnClickListener btnSendListener = new OnClickListener() {
public void onClick(View v) {
if (statusProgres.getText().equals("Closed"))
networktask.SendDataToNetwork(String.valueOf(0) + "/");
else if (statusProgres.getText().equals("100 %"))
networktask.SendDataToNetwork(String.valueOf(100) + "/");
else
networktask.SendDataToNetwork(String.valueOf(statusProgres.getText().toString().substring(0,2)) + "/");
}
};
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (seekBar.getProgress() > 5 && seekBar.getProgress() < 10)
statusProgres.setText("10 %");
else if (seekBar.getProgress() <= 5)
statusProgres.setText("Closed");
else
statusProgres.setText(String.valueOf(seekBar.getProgress() / 10) + "0 %");
Log.i("SeekBar", String.valueOf(seekBar.getProgress()));
}
public class NetworkTask extends AsyncTask<Void, byte[], Boolean> {
Socket nsocket; //Network Socket
InputStream nis; //Network Input Stream
OutputStream nos; //Network Output Stream
@Override
protected void onPreExecute() {
Log.i("AsyncTask", "onPreExecute");
}
@Override
protected Boolean doInBackground(Void… params) {
boolean result = false;
try {
Log.i("AsyncTask", "doInBackground: Creating socket");
SocketAddress sockaddr = new InetSocketAddress("192.168.4.1", 23);
nsocket = new Socket();
nsocket.connect(sockaddr, 5000); //5 second connection timeout
if (nsocket.isConnected()) {
nis = nsocket.getInputStream();
nos = nsocket.getOutputStream();
Log.i("AsyncTask", "doInBackground: Socket created, streams assigned");
Log.i("AsyncTask", "doInBackground: Waiting for inital data…");
byte[] buffer = new byte[4096];
int read = nis.read(buffer, 0, 4096); //This is blocking
while (read != -1) {
byte[] tempdata = new byte[read];
System.arraycopy(buffer, 0, tempdata, 0, read);
publishProgress(tempdata);
Log.i("AsyncTask", "doInBackground: Got some data");
read = nis.read(buffer, 0, 4096); //This is blocking
}
}
}
catch (IOException e) {
e.printStackTrace();
Log.i("AsyncTask", "doInBackground: IOException");
result = true;
} catch (Exception e) {
e.printStackTrace();
Log.i("AsyncTask", "doInBackground: Exception");
result = true;
} finally {
try {
nis.close();
nos.close();
nsocket.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Log.i("AsyncTask", "doInBackground: Finished");
}
return result;
}
public void SendDataToNetwork(final String cmd) { //You run this from the main thread.
new Thread(new Runnable() {
@Override
public void run() {
try {
if (nsocket.isConnected()) {
Log.i("AsyncTask", "SendDataToNetwork: Writing received message to socket");
nos.write(cmd.getBytes());
} else {
Log.i("AsyncTask", "SendDataToNetwork: Cannot send message. Socket is closed");
}
} catch (Exception e) {
Log.i("AsyncTask", "SendDataToNetwork: Message send failed. Caught an exception " + e.getMessage());
}
}
}).start();
}
@Override
protected void onProgressUpdate(byte[]… values) {
if (values.length > 0) {
Log.i("AsyncTask", "onProgressUpdate: " + values[0].length + " bytes received.");
}
}
@Override
protected void onCancelled() {
Log.i("AsyncTask", "Cancelled.");
btnStart.setVisibility(View.VISIBLE);
}
@Override
protected void onPostExecute(Boolean result) {
if (result) {
Log.i("AsyncTask", "onPostExecute: Completed with an Error.");
} else {
Log.i("AsyncTask", "onPostExecute: Completed.");
}
btnStart.setVisibility(View.VISIBLE);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
networktask.cancel(true); //In case the task is currently running
}
}
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Rezumatul lucrării [305724] (ID: 305724)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
