This shows you the differences between two versions of the page.
pm:prj2024:mdinica:robert.grancsa [2024/05/03 21:11] robert.grancsa [Descriere generală] |
pm:prj2024:mdinica:robert.grancsa [2024/05/27 00:16] (current) robert.grancsa |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Bike Infotainment System ====== | + | ====== Bike Infotainment System ====== |
- | ===== Introducere ===== | + | <html> |
- | Autor: **Robert Grancsa 332CA** | + | <head> |
+ | <title>README</title> | ||
+ | <meta charset="utf-8"> | ||
+ | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
+ | <link rel="preconnect" href="https://fonts.googleapis.com"> | ||
+ | <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | ||
+ | <link href="https://fonts.googleapis.com/css2?family=Raleway:ital,wght@0,100..900;1,100..900&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css"> | ||
+ | <style> | ||
+ | code[class*=language-], | ||
+ | pre[class*=language-] { | ||
+ | color: #333; | ||
+ | background: 0 0; | ||
+ | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; | ||
+ | text-align: left; | ||
+ | white-space: pre; | ||
+ | word-spacing: normal; | ||
+ | word-break: normal; | ||
+ | word-wrap: normal; | ||
+ | line-height: 1.4; | ||
+ | -moz-tab-size: 8; | ||
+ | -o-tab-size: 8; | ||
+ | tab-size: 8; | ||
+ | -webkit-hyphens: none; | ||
+ | -moz-hyphens: none; | ||
+ | -ms-hyphens: none; | ||
+ | hyphens: none | ||
+ | } | ||
- | Un infotainment pentru biciclete, vrea să afișeze pe un display informații folositoare despre statusul curent al cursei tale precum: | + | pre[class*=language-] { |
- | * Viteza curentă | + | padding: .8em; |
- | * Temperatura de afară | + | overflow: auto; |
- | * Viteza medie din cursa curentă | + | border-radius: 3px; |
- | * Locația curentă | + | background: #f5f5f5 |
- | * Status despre ce obiecte sunt pe traseu, folosind un model de image recognition, care poate identifica semne de circulație. | + | } |
- | * Înclinația și acceleratia curentă | + | |
- | Pe lângă asta, dispozitivul este conectat la internet, și comunică mereu cu un server pe un Raspberry Pi, unde stochează informațiile, care mai apoi sunt salvate într-o bază de date și afișate într-un dashboard folositor, care îți arată detalii despre ultimele tale curse, cu un istoric cu unde ai fost și ce locuri ai vizitat. | + | :not(pre)>code[class*=language-] { |
+ | padding: .1em; | ||
+ | border-radius: .3em; | ||
+ | white-space: normal; | ||
+ | background: #f5f5f5 | ||
+ | } | ||
- | Acest dispozitiv de infotainment pentru biciclete aduce o serie de beneficii semnificative pentru cicliști, oferindu-le uneltele necesare pentru a monitoriza și îmbunătăți experiența lor de ciclism. | + | .token.blockquote, |
+ | .token.comment { | ||
+ | color: #969896 | ||
+ | } | ||
- | ===== Descriere generală ===== | + | .token.cdata { |
+ | color: #183691 | ||
+ | } | ||
- | Schema proiectului este compusă dintr-un microcontroller ESP32, care conectează partea fizică a proiectului. Conectat la el, putem găsi: | + | .token.doctype, |
+ | .token.macro.property, | ||
+ | .token.punctuation, | ||
+ | .token.variable { | ||
+ | color: #333 | ||
+ | } | ||
- | - GPS - ne va întoarce date despre locația curentă printr-un stream pe UART, aceste date fiind stocate și trimise mai departe la server o dată la câteva secunde. | + | .token.builtin, |
- | - Accelerometru - ne poate afișa starea curentă a bicicletei, dacă se apleacă stânga sau dreapta, sau cât de repede accelerează sau frânează. | + | .token.important, |
- | - Hall Effect senzor - folosit pentru a calcula numărul de revoluții pe secundă al bicicletei, pentru a afișa o estimare corectă a vitezei. | + | .token.keyword, |
- | - Camera - va transmite cadre o dată pe secundă către server, care mai apoi va întoarce date despre cadrul curent, mai apoi fiind afișat pe display. | + | .token.operator, |
- | - Display - aici vor fi afișate toate datele importante, care nu sunt transmise către server dar care ajută la a vedea mai ușor starea curentă. | + | .token.rule { |
- | - Serverul Raspberry Pi - face conexiunea cu toate instrumentele de la bord, care le stochează pe o bază de date locală, și după le putem interoga pe un front-end cu un dashboard, care ne arată statistici despre ultimele curse. | + | color: #a71d5d |
+ | } | ||
- | {{:pm:prj2024:mdinica:robert.grancsa:pm_project_diagram.drawio.png?700|}} | + | .token.attr-value, |
+ | .token.regex, | ||
+ | .token.string, | ||
+ | .token.url { | ||
+ | color: #183691 | ||
+ | } | ||
+ | .token.atrule, | ||
+ | .token.boolean, | ||
+ | .token.code, | ||
+ | .token.command, | ||
+ | .token.constant, | ||
+ | .token.entity, | ||
+ | .token.number, | ||
+ | .token.property, | ||
+ | .token.symbol { | ||
+ | color: #0086b3 | ||
+ | } | ||
- | ===== Hardware Design ===== | + | .token.prolog, |
+ | .token.selector, | ||
+ | .token.tag { | ||
+ | color: #63a35c | ||
+ | } | ||
- | <note tip> | + | .token.attr-name, |
- | Aici puneţi tot ce ţine de hardware design: | + | .token.class, |
- | * listă de piese | + | .token.class-name, |
- | * scheme electrice (se pot lua şi de pe Internet şi din datasheet-uri, e.g. http://www.captain.at/electronic-atmega16-mmc-schematic.png) | + | .token.function, |
- | * diagrame de semnal | + | .token.id, |
- | * rezultatele simulării | + | .token.namespace, |
- | </note> | + | .token.pseudo-class, |
+ | .token.pseudo-element, | ||
+ | .token.url-reference .token.variable { | ||
+ | color: #795da3 | ||
+ | } | ||
- | ===== Software Design ===== | + | .token.entity { |
+ | cursor: help | ||
+ | } | ||
+ | .token.title, | ||
+ | .token.title .token.punctuation { | ||
+ | font-weight: 700; | ||
+ | color: #1d3e81 | ||
+ | } | ||
- | <note tip> | + | .token.list { |
- | Descrierea codului aplicaţiei (firmware): | + | color: #ed6a43 |
- | * mediu de dezvoltare (if any) (e.g. AVR Studio, CodeVisionAVR) | + | } |
- | * librării şi surse 3rd-party (e.g. Procyon AVRlib) | + | |
- | * algoritmi şi structuri pe care plănuiţi să le implementaţi | + | |
- | * (etapa 3) surse şi funcţii implementate | + | |
- | </note> | + | |
- | ===== Rezultate Obţinute ===== | + | .token.inserted { |
+ | background-color: #eaffea; | ||
+ | color: #55a532 | ||
+ | } | ||
- | <note tip> | + | .token.deleted { |
- | Care au fost rezultatele obţinute în urma realizării proiectului vostru. | + | background-color: #ffecec; |
- | </note> | + | color: #bd2c00 |
+ | } | ||
- | ===== Concluzii ===== | + | .token.bold { |
+ | font-weight: 700 | ||
+ | } | ||
- | ===== Download ===== | + | .token.italic { |
+ | font-style: italic | ||
+ | } | ||
- | <note warning> | + | .language-json .token.property { |
- | O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului: surse, scheme, etc. Un fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-). | + | color: #183691 |
+ | } | ||
- | Fişierele se încarcă pe wiki folosind facilitatea **Add Images or other files**. Namespace-ul în care se încarcă fişierele este de tipul **:pm:prj20??:c?** sau **:pm:prj20??:c?:nume_student** (dacă este cazul). **Exemplu:** Dumitru Alin, 331CC -> **:pm:prj2009:cc:dumitru_alin**. | + | .language-markup .token.tag .token.punctuation { |
- | </note> | + | color: #333 |
+ | } | ||
- | ===== Jurnal ===== | + | .language-css .token.function, |
+ | code.language-css { | ||
+ | color: #0086b3 | ||
+ | } | ||
- | <note tip> | + | .language-yaml .token.atrule { |
- | Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului. | + | color: #63a35c |
- | </note> | + | } |
- | ===== Bibliografie/Resurse ===== | + | code.language-yaml { |
+ | color: #183691 | ||
+ | } | ||
- | <note> | + | .language-ruby .token.function { |
- | Listă cu documente, datasheet-uri, resurse Internet folosite, eventual grupate pe **Resurse Software** şi **Resurse Hardware**. | + | color: #333 |
- | </note> | + | } |
- | <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> | + | .language-markdown .token.url { |
+ | color: #795da3 | ||
+ | } | ||
+ | .language-makefile .token.symbol { | ||
+ | color: #795da3 | ||
+ | } | ||
+ | .language-makefile .token.variable { | ||
+ | color: #183691 | ||
+ | } | ||
+ | |||
+ | .language-makefile .token.builtin { | ||
+ | color: #0086b3 | ||
+ | } | ||
+ | |||
+ | .language-bash .token.keyword { | ||
+ | color: #0086b3 | ||
+ | } | ||
+ | |||
+ | pre[data-line] { | ||
+ | position: relative; | ||
+ | padding: 1em 0 1em 3em | ||
+ | } | ||
+ | |||
+ | pre[data-line] .line-highlight-wrapper { | ||
+ | position: absolute; | ||
+ | top: 0; | ||
+ | left: 0; | ||
+ | background-color: transparent; | ||
+ | display: block; | ||
+ | width: 100% | ||
+ | } | ||
+ | |||
+ | pre[data-line] .line-highlight { | ||
+ | position: absolute; | ||
+ | left: 0; | ||
+ | right: 0; | ||
+ | padding: inherit 0; | ||
+ | margin-top: 1em; | ||
+ | background: hsla(24, 20%, 50%, .08); | ||
+ | background: linear-gradient(to right, hsla(24, 20%, 50%, .1) 70%, hsla(24, 20%, 50%, 0)); | ||
+ | pointer-events: none; | ||
+ | line-height: inherit; | ||
+ | white-space: pre | ||
+ | } | ||
+ | |||
+ | pre[data-line] .line-highlight:before, | ||
+ | pre[data-line] .line-highlight[data-end]:after { | ||
+ | content: attr(data-start); | ||
+ | position: absolute; | ||
+ | top: .4em; | ||
+ | left: .6em; | ||
+ | min-width: 1em; | ||
+ | padding: 0 .5em; | ||
+ | background-color: hsla(24, 20%, 50%, .4); | ||
+ | color: #f4f1ef; | ||
+ | font: bold 65%/1.5 sans-serif; | ||
+ | text-align: center; | ||
+ | vertical-align: .3em; | ||
+ | border-radius: 999px; | ||
+ | text-shadow: none; | ||
+ | box-shadow: 0 1px #fff | ||
+ | } | ||
+ | |||
+ | pre[data-line] .line-highlight[data-end]:after { | ||
+ | content: attr(data-end); | ||
+ | top: auto; | ||
+ | bottom: .4em | ||
+ | } | ||
+ | |||
+ | html body { | ||
+ | font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; | ||
+ | font-size: 16px; | ||
+ | line-height: 1.6; | ||
+ | color: #333; | ||
+ | background-color: #fff; | ||
+ | overflow: initial; | ||
+ | box-sizing: border-box; | ||
+ | word-wrap: break-word | ||
+ | } | ||
+ | |||
+ | html body>:first-child { | ||
+ | margin-top: 0 | ||
+ | } | ||
+ | |||
+ | html body h1, | ||
+ | html body h2, | ||
+ | html body h3, | ||
+ | html body h4, | ||
+ | html body h5, | ||
+ | html body h6 { | ||
+ | line-height: 1.2; | ||
+ | margin-top: 1em; | ||
+ | margin-bottom: 16px; | ||
+ | color: #000 | ||
+ | } | ||
+ | |||
+ | html body h1 { | ||
+ | font-size: 2.25em; | ||
+ | font-weight: 300; | ||
+ | padding-bottom: .3em | ||
+ | } | ||
+ | |||
+ | html body h2 { | ||
+ | font-size: 1.75em; | ||
+ | font-weight: 400; | ||
+ | padding-bottom: .3em | ||
+ | } | ||
+ | |||
+ | html body h3 { | ||
+ | font-size: 1.5em; | ||
+ | font-weight: 500 | ||
+ | } | ||
+ | |||
+ | html body h4 { | ||
+ | font-size: 1.25em; | ||
+ | font-weight: 600 | ||
+ | } | ||
+ | |||
+ | html body h5 { | ||
+ | font-size: 1.1em; | ||
+ | font-weight: 600 | ||
+ | } | ||
+ | |||
+ | html body h6 { | ||
+ | font-size: 1em; | ||
+ | font-weight: 600 | ||
+ | } | ||
+ | |||
+ | html body h1, | ||
+ | html body h2, | ||
+ | html body h3, | ||
+ | html body h4, | ||
+ | html body h5 { | ||
+ | font-weight: 600 | ||
+ | } | ||
+ | |||
+ | html body h5 { | ||
+ | font-size: 1em | ||
+ | } | ||
+ | |||
+ | html body h6 { | ||
+ | color: #5c5c5c | ||
+ | } | ||
+ | |||
+ | html body strong { | ||
+ | color: #000 | ||
+ | } | ||
+ | |||
+ | html body del { | ||
+ | color: #5c5c5c | ||
+ | } | ||
+ | |||
+ | html body a:not([href]) { | ||
+ | color: inherit; | ||
+ | text-decoration: none | ||
+ | } | ||
+ | |||
+ | html body a { | ||
+ | color: #08c; | ||
+ | text-decoration: none | ||
+ | } | ||
+ | |||
+ | html body a:hover { | ||
+ | color: #00a3f5; | ||
+ | text-decoration: none | ||
+ | } | ||
+ | |||
+ | html body img { | ||
+ | max-width: 100% | ||
+ | } | ||
+ | |||
+ | html body>p { | ||
+ | margin-top: 0; | ||
+ | margin-bottom: 16px; | ||
+ | word-wrap: break-word | ||
+ | } | ||
+ | |||
+ | html body>ol, | ||
+ | html body>ul { | ||
+ | margin-bottom: 16px | ||
+ | } | ||
+ | |||
+ | html body ol, | ||
+ | html body ul { | ||
+ | padding-left: 2em | ||
+ | } | ||
+ | |||
+ | html body ol.no-list, | ||
+ | html body ul.no-list { | ||
+ | padding: 0; | ||
+ | list-style-type: none | ||
+ | } | ||
+ | |||
+ | html body ol ol, | ||
+ | html body ol ul, | ||
+ | html body ul ol, | ||
+ | html body ul ul { | ||
+ | margin-top: 0; | ||
+ | margin-bottom: 0 | ||
+ | } | ||
+ | |||
+ | html body li { | ||
+ | margin-bottom: 0 | ||
+ | } | ||
+ | |||
+ | html body li.task-list-item { | ||
+ | list-style: none | ||
+ | } | ||
+ | |||
+ | html body li>p { | ||
+ | margin-top: 0; | ||
+ | margin-bottom: 0 | ||
+ | } | ||
+ | |||
+ | html body .task-list-item-checkbox { | ||
+ | margin: 0 .2em .25em -1.8em; | ||
+ | vertical-align: middle | ||
+ | } | ||
+ | |||
+ | html body .task-list-item-checkbox:hover { | ||
+ | cursor: pointer | ||
+ | } | ||
+ | |||
+ | html body blockquote { | ||
+ | margin: 16px 0; | ||
+ | font-size: inherit; | ||
+ | padding: 0 15px; | ||
+ | color: #5c5c5c; | ||
+ | background-color: #f0f0f0; | ||
+ | border-left: 4px solid #d6d6d6 | ||
+ | } | ||
+ | |||
+ | html body blockquote>:first-child { | ||
+ | margin-top: 0 | ||
+ | } | ||
+ | |||
+ | html body blockquote>:last-child { | ||
+ | margin-bottom: 0 | ||
+ | } | ||
+ | |||
+ | html body hr { | ||
+ | height: 4px; | ||
+ | margin: 32px 0; | ||
+ | background-color: #d6d6d6; | ||
+ | border: 0 none | ||
+ | } | ||
+ | |||
+ | html body table { | ||
+ | margin: 10px 0 15px 0; | ||
+ | border-collapse: collapse; | ||
+ | border-spacing: 0; | ||
+ | display: block; | ||
+ | width: 100%; | ||
+ | overflow: auto; | ||
+ | word-break: normal; | ||
+ | word-break: keep-all | ||
+ | } | ||
+ | |||
+ | html body table th { | ||
+ | font-weight: 700; | ||
+ | color: #000 | ||
+ | } | ||
+ | |||
+ | html body table td, | ||
+ | html body table th { | ||
+ | border: 1px solid #d6d6d6; | ||
+ | padding: 6px 13px | ||
+ | } | ||
+ | |||
+ | html body dl { | ||
+ | padding: 0 | ||
+ | } | ||
+ | |||
+ | html body dl dt { | ||
+ | padding: 0; | ||
+ | margin-top: 16px; | ||
+ | font-size: 1em; | ||
+ | font-style: italic; | ||
+ | font-weight: 700 | ||
+ | } | ||
+ | |||
+ | html body dl dd { | ||
+ | padding: 0 16px; | ||
+ | margin-bottom: 16px | ||
+ | } | ||
+ | |||
+ | html body code { | ||
+ | font-family: Menlo, Monaco, Consolas, 'Courier New', monospace; | ||
+ | font-size: .85em; | ||
+ | color: #000; | ||
+ | background-color: #f0f0f0; | ||
+ | border-radius: 3px; | ||
+ | padding: .2em 0 | ||
+ | } | ||
+ | |||
+ | html body code::after, | ||
+ | html body code::before { | ||
+ | letter-spacing: -.2em; | ||
+ | content: '\00a0' | ||
+ | } | ||
+ | |||
+ | html body pre>code { | ||
+ | padding: 0; | ||
+ | margin: 0; | ||
+ | word-break: normal; | ||
+ | white-space: pre; | ||
+ | background: 0 0; | ||
+ | border: 0 | ||
+ | } | ||
+ | |||
+ | html body .highlight { | ||
+ | margin-bottom: 16px | ||
+ | } | ||
+ | |||
+ | html body .highlight pre, | ||
+ | html body pre { | ||
+ | padding: 1em; | ||
+ | overflow: auto; | ||
+ | line-height: 1.45; | ||
+ | border: #d6d6d6; | ||
+ | border-radius: 3px | ||
+ | } | ||
+ | |||
+ | html body .highlight pre { | ||
+ | margin-bottom: 0; | ||
+ | word-break: normal | ||
+ | } | ||
+ | |||
+ | html body pre code, | ||
+ | html body pre tt { | ||
+ | display: inline; | ||
+ | max-width: initial; | ||
+ | padding: 0; | ||
+ | margin: 0; | ||
+ | overflow: initial; | ||
+ | line-height: inherit; | ||
+ | word-wrap: normal; | ||
+ | background-color: transparent; | ||
+ | border: 0 | ||
+ | } | ||
+ | |||
+ | html body pre code:after, | ||
+ | html body pre code:before, | ||
+ | html body pre tt:after, | ||
+ | html body pre tt:before { | ||
+ | content: normal | ||
+ | } | ||
+ | |||
+ | html body blockquote, | ||
+ | html body dl, | ||
+ | html body ol, | ||
+ | html body p, | ||
+ | html body pre, | ||
+ | html body ul { | ||
+ | margin-top: 0; | ||
+ | margin-bottom: 16px | ||
+ | } | ||
+ | |||
+ | html body kbd { | ||
+ | color: #000; | ||
+ | border: 1px solid #d6d6d6; | ||
+ | border-bottom: 2px solid #c7c7c7; | ||
+ | padding: 2px 4px; | ||
+ | background-color: #f0f0f0; | ||
+ | border-radius: 3px | ||
+ | } | ||
+ | |||
+ | @media print { | ||
+ | html body { | ||
+ | background-color: #fff | ||
+ | } | ||
+ | |||
+ | html body h1, | ||
+ | html body h2, | ||
+ | html body h3, | ||
+ | html body h4, | ||
+ | html body h5, | ||
+ | html body h6 { | ||
+ | color: #000; | ||
+ | page-break-after: avoid | ||
+ | } | ||
+ | |||
+ | html body blockquote { | ||
+ | color: #5c5c5c | ||
+ | } | ||
+ | |||
+ | html body pre { | ||
+ | page-break-inside: avoid | ||
+ | } | ||
+ | |||
+ | html body table { | ||
+ | display: table | ||
+ | } | ||
+ | |||
+ | html body img { | ||
+ | display: block; | ||
+ | max-width: 100%; | ||
+ | max-height: 100% | ||
+ | } | ||
+ | |||
+ | html body code, | ||
+ | html body pre { | ||
+ | word-wrap: break-word; | ||
+ | white-space: pre | ||
+ | } | ||
+ | } | ||
+ | |||
+ | .markdown-preview { | ||
+ | width: 100%; | ||
+ | height: 100%; | ||
+ | box-sizing: border-box | ||
+ | } | ||
+ | |||
+ | .markdown-preview ul { | ||
+ | list-style: disc | ||
+ | } | ||
+ | |||
+ | .markdown-preview ul ul { | ||
+ | list-style: circle | ||
+ | } | ||
+ | |||
+ | .markdown-preview ul ul ul { | ||
+ | list-style: square | ||
+ | } | ||
+ | |||
+ | .markdown-preview ol { | ||
+ | list-style: decimal | ||
+ | } | ||
+ | |||
+ | .markdown-preview ol ol, | ||
+ | .markdown-preview ul ol { | ||
+ | list-style-type: lower-roman | ||
+ | } | ||
+ | |||
+ | .markdown-preview ol ol ol, | ||
+ | .markdown-preview ol ul ol, | ||
+ | .markdown-preview ul ol ol, | ||
+ | .markdown-preview ul ul ol { | ||
+ | list-style-type: lower-alpha | ||
+ | } | ||
+ | |||
+ | .markdown-preview .newpage, | ||
+ | .markdown-preview .pagebreak { | ||
+ | page-break-before: always | ||
+ | } | ||
+ | |||
+ | .markdown-preview pre.line-numbers { | ||
+ | position: relative; | ||
+ | padding-left: 3.8em; | ||
+ | counter-reset: linenumber | ||
+ | } | ||
+ | |||
+ | .markdown-preview pre.line-numbers>code { | ||
+ | position: relative | ||
+ | } | ||
+ | |||
+ | .markdown-preview pre.line-numbers .line-numbers-rows { | ||
+ | position: absolute; | ||
+ | pointer-events: none; | ||
+ | top: 1em; | ||
+ | font-size: 100%; | ||
+ | left: 0; | ||
+ | width: 3em; | ||
+ | letter-spacing: -1px; | ||
+ | border-right: 1px solid #999; | ||
+ | -webkit-user-select: none; | ||
+ | -moz-user-select: none; | ||
+ | -ms-user-select: none; | ||
+ | user-select: none | ||
+ | } | ||
+ | |||
+ | .markdown-preview pre.line-numbers .line-numbers-rows>span { | ||
+ | pointer-events: none; | ||
+ | display: block; | ||
+ | counter-increment: linenumber | ||
+ | } | ||
+ | |||
+ | .markdown-preview pre.line-numbers .line-numbers-rows>span:before { | ||
+ | content: counter(linenumber); | ||
+ | color: #999; | ||
+ | display: block; | ||
+ | padding-right: .8em; | ||
+ | text-align: right | ||
+ | } | ||
+ | |||
+ | .markdown-preview .mathjax-exps .MathJax_Display { | ||
+ | text-align: center !important | ||
+ | } | ||
+ | |||
+ | .markdown-preview:not([data-for=preview]) .code-chunk .code-chunk-btn-group { | ||
+ | display: none | ||
+ | } | ||
+ | |||
+ | .markdown-preview:not([data-for=preview]) .code-chunk .status { | ||
+ | display: none | ||
+ | } | ||
+ | |||
+ | .markdown-preview:not([data-for=preview]) .code-chunk .output-div { | ||
+ | margin-bottom: 16px | ||
+ | } | ||
+ | |||
+ | .markdown-preview .md-toc { | ||
+ | padding: 0 | ||
+ | } | ||
+ | |||
+ | .markdown-preview .md-toc .md-toc-link-wrapper .md-toc-link { | ||
+ | display: inline; | ||
+ | padding: .25rem 0 | ||
+ | } | ||
+ | |||
+ | .markdown-preview .md-toc .md-toc-link-wrapper .md-toc-link div, | ||
+ | .markdown-preview .md-toc .md-toc-link-wrapper .md-toc-link p { | ||
+ | display: inline | ||
+ | } | ||
+ | |||
+ | .markdown-preview .md-toc .md-toc-link-wrapper.highlighted .md-toc-link { | ||
+ | font-weight: 800 | ||
+ | } | ||
+ | |||
+ | .scrollbar-style::-webkit-scrollbar { | ||
+ | width: 8px | ||
+ | } | ||
+ | |||
+ | .scrollbar-style::-webkit-scrollbar-track { | ||
+ | border-radius: 10px; | ||
+ | background-color: transparent | ||
+ | } | ||
+ | |||
+ | .scrollbar-style::-webkit-scrollbar-thumb { | ||
+ | border-radius: 5px; | ||
+ | background-color: rgba(150, 150, 150, .66); | ||
+ | border: 4px solid rgba(150, 150, 150, .66); | ||
+ | background-clip: content-box | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode]) { | ||
+ | position: relative; | ||
+ | width: 100%; | ||
+ | height: 100%; | ||
+ | top: 0; | ||
+ | left: 0; | ||
+ | margin: 0; | ||
+ | padding: 0; | ||
+ | overflow: auto | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode]) .markdown-preview { | ||
+ | position: relative; | ||
+ | top: 0; | ||
+ | min-height: 100vh | ||
+ | } | ||
+ | |||
+ | @media screen and (min-width:914px) { | ||
+ | html body[for=html-export]:not([data-presentation-mode]) .markdown-preview { | ||
+ | padding: 2em calc(50% - 457px + 2em) | ||
+ | } | ||
+ | } | ||
+ | |||
+ | @media screen and (max-width:914px) { | ||
+ | html body[for=html-export]:not([data-presentation-mode]) .markdown-preview { | ||
+ | padding: 2em | ||
+ | } | ||
+ | } | ||
+ | |||
+ | @media screen and (max-width:450px) { | ||
+ | html body[for=html-export]:not([data-presentation-mode]) .markdown-preview { | ||
+ | font-size: 14px !important; | ||
+ | padding: 1em | ||
+ | } | ||
+ | } | ||
+ | |||
+ | @media print { | ||
+ | html body[for=html-export]:not([data-presentation-mode]) #sidebar-toc-btn { | ||
+ | display: none | ||
+ | } | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode]) #sidebar-toc-btn { | ||
+ | position: fixed; | ||
+ | bottom: 8px; | ||
+ | left: 8px; | ||
+ | font-size: 28px; | ||
+ | cursor: pointer; | ||
+ | color: inherit; | ||
+ | z-index: 99; | ||
+ | width: 32px; | ||
+ | text-align: center; | ||
+ | opacity: .4 | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] #sidebar-toc-btn { | ||
+ | opacity: 1 | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc { | ||
+ | position: fixed; | ||
+ | top: 0; | ||
+ | left: 0; | ||
+ | width: 300px; | ||
+ | height: 100%; | ||
+ | padding: 32px 0 48px 0; | ||
+ | font-size: 14px; | ||
+ | box-shadow: 0 0 4px rgba(150, 150, 150, .33); | ||
+ | box-sizing: border-box; | ||
+ | overflow: auto; | ||
+ | background-color: inherit | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar { | ||
+ | width: 8px | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar-track { | ||
+ | border-radius: 10px; | ||
+ | background-color: transparent | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar-thumb { | ||
+ | border-radius: 5px; | ||
+ | background-color: rgba(150, 150, 150, .66); | ||
+ | border: 4px solid rgba(150, 150, 150, .66); | ||
+ | background-clip: content-box | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc a { | ||
+ | text-decoration: none | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc { | ||
+ | padding: 0 16px | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper .md-toc-link { | ||
+ | display: inline; | ||
+ | padding: .25rem 0 | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper .md-toc-link div, | ||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper .md-toc-link p { | ||
+ | display: inline | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper.highlighted .md-toc-link { | ||
+ | font-weight: 800 | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview { | ||
+ | left: 300px; | ||
+ | width: calc(100% - 300px); | ||
+ | padding: 2em calc(50% - 457px - 300px / 2); | ||
+ | margin: 0; | ||
+ | box-sizing: border-box | ||
+ | } | ||
+ | |||
+ | @media screen and (max-width:1274px) { | ||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview { | ||
+ | padding: 2em | ||
+ | } | ||
+ | } | ||
+ | |||
+ | @media screen and (max-width:450px) { | ||
+ | html body[for=html-export]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview { | ||
+ | width: 100% | ||
+ | } | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode]):not([html-show-sidebar-toc]) .markdown-preview { | ||
+ | left: 50%; | ||
+ | transform: translateX(-50%) | ||
+ | } | ||
+ | |||
+ | html body[for=html-export]:not([data-presentation-mode]):not([html-show-sidebar-toc]) .md-sidebar-toc { | ||
+ | display: none | ||
+ | } | ||
+ | |||
+ | /* Please visit the URL below for more information: */ | ||
+ | /* https://shd101wyy.github.io/markdown-preview-enhanced/#/customize-css */ | ||
+ | </style> | ||
+ | <!-- The content below will be included at the end of the <head> element. --> | ||
+ | <script type="text/javascript"> | ||
+ | document.addEventListener("DOMContentLoaded", function () { | ||
+ | | ||
+ | }); | ||
+ | </script> | ||
+ | </head> | ||
+ | |||
+ | <body for="html-export"> | ||
+ | |||
+ | |||
+ | <div class="crossnote markdown-preview "> | ||
+ | |||
+ | <h1 style="font-family:Raleway; font-weight: 700;" id="bike-infotainment-system">Bike Infotainment System </h1> | ||
+ | <h2 style="font-family:Raleway; font-weight: 600;" id="introducere">Introducere </h2> | ||
+ | <p style="font-family:Roboto">Autor: <strong>Robert Grancsa 332CA</strong></p> | ||
+ | <p style="font-family:Roboto">Un infotainment pentru biciclete, vrea să afișeze pe un display informații folositoare despre statusul | ||
+ | curent al cursei tale precum:</p> | ||
+ | <ul style="font-family:Roboto"> | ||
+ | <li>Viteza curentă</li> | ||
+ | <li>Temperatura de afară</li> | ||
+ | <li>Viteza medie din cursa curentă</li> | ||
+ | <li>Locația curentă</li> | ||
+ | <li>Status despre ce obiecte sunt pe traseu, folosind un model de image recognition, care poate | ||
+ | identifica semne de circulație.</li> | ||
+ | <li>Înclinația și acceleratia curentă</li> | ||
+ | </ul> | ||
+ | <p style="font-family:Roboto">Pe lângă asta, dispozitivul este conectat la internet, și comunică mereu cu un server pe un Raspberry Pi, | ||
+ | unde stochează informațiile, care mai apoi sunt salvate într-o bază de date și afișate într-un | ||
+ | dashboard folositor, care îți arată detalii despre ultimele tale curse, cu un istoric cu unde ai fost | ||
+ | și ce locuri ai vizitat.</p> | ||
+ | <p style="font-family:Roboto">Acest dispozitiv de infotainment pentru biciclete aduce o serie de beneficii semnificative pentru | ||
+ | cicliști, oferindu-le uneltele necesare pentru a monitoriza și îmbunătăți experiența lor de ciclism. | ||
+ | </p> | ||
+ | <h2 style="font-family:Raleway; font-weight: 600;" id="descriere-generală">Descriere generală </h2> | ||
+ | <p>Schema proiectului este compusă dintr-un microcontroller ESP32, care conectează partea fizică a | ||
+ | proiectului. Conectat la el, putem găsi:</p> | ||
+ | <ol style="font-family:Roboto"> | ||
+ | <li>GPS - ne va întoarce date despre locația curentă printr-un stream pe UART, aceste date fiind | ||
+ | stocate și trimise mai departe la server o dată la câteva secunde.</li> | ||
+ | <li>Accelerometru - ne poate afișa starea curentă a bicicletei, dacă se apleacă stânga sau dreapta, | ||
+ | sau cât de repede accelerează sau frânează.</li> | ||
+ | <li>Hall Effect senzor - folosit pentru a calcula numărul de revoluții pe secundă al bicicletei, | ||
+ | pentru a afișa o estimare corectă a vitezei.</li> | ||
+ | <li>Camera - va transmite cadre o dată pe secundă către server, care mai apoi va întoarce date despre | ||
+ | cadrul curent, mai apoi fiind afișat pe display.</li> | ||
+ | <li>Display - aici vor fi afișate toate datele importante, care nu sunt transmise către server dar | ||
+ | care ajută la a vedea mai ușor starea curentă.</li> | ||
+ | <li>Serverul Raspberry Pi - face conexiunea cu toate instrumentele de la bord, care le stochează pe o | ||
+ | bază de date locală, și după le putem interoga pe un front-end cu un dashboard, care ne arată | ||
+ | statistici despre ultimele curse.</li> | ||
+ | </ol> | ||
+ | <p><img src="https://i.imgur.com/X5e3Lpz.png" alt="Diagrama proiectului"></p> | ||
+ | <h2 style="font-family:Raleway; font-weight: 600;" id="hardware-design">Hardware Design </h2> | ||
+ | <p style="font-family:Roboto">Schematicul produsul se poate vedea mai jos. Am incercat sa conectez pinii spefici SPI pe pinii specifici | ||
+ | de SPI, pentru GPS m-am folosit de pinii de UART si pentru camera am ales sa folosesc pinii cei mai | ||
+ | apropiati unul de altul pentru date, ca sa nu fie overlap la conectarea firelor.</p> | ||
+ | <p><img src="assets/Schematic.png" alt="Schematicul"></p> | ||
+ | <p style="font-family:Roboto">Tabelul cu piesele folosite se poate vedea mai jos.</p> | ||
+ | <table> | ||
+ | <thead> | ||
+ | <tr> | ||
+ | <th>Nume Piesa</th> | ||
+ | <th>Model</th> | ||
+ | <th>Protocol</th> | ||
+ | </tr> | ||
+ | </thead> | ||
+ | <tbody> | ||
+ | <tr> | ||
+ | <td>Microcontroller</td> | ||
+ | <td>ESP32-WROOM32</td> | ||
+ | <td>-</td> | ||
+ | </tr> | ||
+ | <tr> | ||
+ | <td>Display</td> | ||
+ | <td>ST7735</td> | ||
+ | <td>SPI</td> | ||
+ | </tr> | ||
+ | <tr> | ||
+ | <td>Camera</td> | ||
+ | <td>OV7670</td> | ||
+ | <td>I2S</td> | ||
+ | </tr> | ||
+ | <tr> | ||
+ | <td>GPS</td> | ||
+ | <td>GY-GPS6MV2</td> | ||
+ | <td>UART</td> | ||
+ | </tr> | ||
+ | <tr> | ||
+ | <td>Hall Effect Sensor</td> | ||
+ | <td>YS-27</td> | ||
+ | <td>ADC</td> | ||
+ | </tr> | ||
+ | </tbody> | ||
+ | </table> | ||
+ | <h2 style="font-family:Raleway; font-weight: 600;" id="software-design">Software Design </h2> | ||
+ | <p>Codul este momentan functional pe partea de cod main, functionalitatile extra nu au putut fi duse pana la | ||
+ | capat din cauza limitarilor hardware (ram insuficient pentru a encoda poze in base64), dar cele de | ||
+ | baza cum ar fi tracking de viteza functioneaza corect.</p> | ||
+ | <h3 style="font-family:Raleway; font-weight: 500;" id="biblioteci">Biblioteci </h3> | ||
+ | <p>Au fost folosite biblioteci precum:</p> | ||
+ | <ul> | ||
+ | <li>Adafruit_GFX - pentru display si grafice</li> | ||
+ | <li>OV7670 - pentru camera si sincronizare de ceas pe I2C/I2S</li> | ||
+ | <li>TinyGPS++ - pentru a citi datele pe UART pe GPS</li> | ||
+ | <li>WiFi, WiFiMulti, WiFiClient, HTTPClient - pentru transfer de date via internet</li> | ||
+ | </ul> | ||
+ | <h3 style="font-family:Raleway; font-weight: 500;" id="features">Features </h3> | ||
+ | <p>Au fost folosite doua thread-uri separate, unul care se ocupata de citirea datelor, actualizarea lor si | ||
+ | afisarea pe ecran de fiecare data cand se gaseste o actualizare a vitezea via Hall Effect sensor, iar | ||
+ | al doilea thread, care e pinned la un alt core fata de primul, se ocupa de transmisia prin wifi a | ||
+ | datelor catre back-end-ul care tine un loc al datelor.</p> | ||
+ | <p>Am folosit si intreruperi pentru a detecta butonul apasat, ca mai apoi sa pot cicla intre ecranul | ||
+ | principal de viteza, si ecranul care arata display-ul.</p> | ||
+ | <p>Serverul este scris in Express, si se foloseste de MongoDB sa salveze datele persistent.<br> | ||
+ | El este hostat pe raspberry pi, si pastreaza mereu legatura la device. Acest back-end face si | ||
+ | request-uri catre Google Cloud sa clasifice obiectele din imagine de pe camera,<br> | ||
+ | care mai apoi intoarce daca a gasit vreun semn de circulatie sau vreun danger pe imagine, si in caz ca | ||
+ | se gaseste ceva dangerous imaginea respectiva este si ea salvata in baza de date ca logging.</p> | ||
+ | <p>Aceste date pot fi vazute dupa vazute dupa aceea pe front-end-ul scris in React.</p> | ||
+ | <h3 style="font-family:Raleway; font-weight: 500;" id="schelet">Schelet </h3> | ||
+ | <p>Codul contine partea de init, care initializeaza wifi-ul, si fiecare senzor valabil precum gps-ul, camera | ||
+ | si ecranul. Apoi avem partea de cod care introduce intreruperile si pornirea de core-uri pentru | ||
+ | task-ul de send, si cel de update a ecranului.</p> | ||
+ | <p>Se foloseste de multe functii ajutatoare, pentru a trimite datele, pentru a da refresh la ecran si pentru | ||
+ | a calcula distanta parcursa de la ultima activare.</p> | ||
+ | <h3 style="font-family:Raleway; font-weight: 500;" id="calibrare">Calibrare </h3> | ||
+ | <p>Pentru senzorul Hall, calibrarea a fost facuta folosind print-uri la serial si folosind un magnet si | ||
+ | regland potentiometrul de pe device pentru a ajunge la sensitivitatea dorita.</p> | ||
+ | <h2 style="font-family:Raleway; font-weight: 600;" id="rezultate-obținute">Rezultate Obținute </h2> | ||
+ | <p>Codul sursa pentru proiect poate fi gasit <a href="https://github.com/RobertGrancsa/PM_Project">aici</a> | ||
+ | </p> | ||
+ | <p><img href="https://github.com/RobertGrancsa/PM_Project" src="https://opengraph.githubassets.com/6f91aeeafc7c48641ebbb89c91265b7bede1f65b01d95f3c0df5048f17a0d8a2/RobertGrancsa/PM_Project" | ||
+ | alt="codul sursa"></p> | ||
+ | <h2 style="font-family:Raleway; font-weight: 600;" id="download">Download </h2> | ||
+ | <p>Proiectul poate fi gasit pe <a href="https://github.com/RobertGrancsa/PM_Project">github</a>, si | ||
+ | descarcat si compilat local.</p> | ||
+ | </div> | ||
+ | </body> | ||
+ | </html> |