diff --git a/README.md b/README.md index f644cb4..81b7801 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,55 @@ -# A fancy titled project - Project documentation +# ECLIPSE - Project documentation -__:bangbang: Important :bangbang:__ This file is the documentation of your project. It should contain all requirements, crucial information and steps to reproduce your work. It may be used to evaluate your work at the final presentation, so make it understandable, easy to use and up-to-date. +![](images/eclipse_logo.png) -__:bangbang: Remark :bangbang:__ Remember to make your code clean and well documented +## Project structure -[Markdown basic syntax](https://www.markdownguide.org/basic-syntax/) +``` +. +├── images +├── src +│ ├── computer-vision +│ ├── hardware +│ ├── rpi +│ ├── desktop +│ └── stm32 +├── project_plan +│ ├── project_charter.md +│ └── project_tasks_n_schedule.md +└── report + └── report.md -### Do's +``` -1. keep your repository clean -2. document your code -3. upload just the source code -4. upload compressed images -5. instead of movies upload gifs -6. repository should be as lightweight as possible +## Git usage -### Don'ts +First install git and oben `git bash` in a directory where you want to clone the repo. Then clone the repo with: -1. don't upload binary and temporary files -2. don't upload unnecesary copies of your files -3. don't upload heavy files -4. don't upload configuration files of your ide +```bash +git clone https://github.com/kcir-roberto/projects-jj-eclipse.git +``` +In order to avoid conflicts, everybody should use their own branch. Please do not commit to master. To check on which branch you are, run +``` +git branch --show-current +``` -## Useful examples of markdown syntax +If it shows `main`, don't create any commits. Instead, switch to your branch using: -### Code +```bash +git checkout +``` -Code blocks are intended by four space or one tab. So this is a block code: +Or, if you don't have a branch yet, create one with: - if (linkPortCore * 23) { - clip.cc(guid, importPrinter.webmail_password_domain.usb_printer_gif( - spool_rpc, seoTextThunderbolt), frame_cell_ole); - tracerouteSystem += -5; - } else { - queueDisk(ppp); - gammaDesktopDns = mailDiskMemory; - dragBalanceWired = quicktime_word_macro(illegal_hibernate_srgb, 962835 + - 5); - } - +```bash +git branch +``` -### Tables +Please, as a name of your branch select `your name/topic`. This way its visible who is the owner and what is the purpose of the branch. +Once you are on your branch, use `git add`, `git commit` and `git push` to manage your stuff. -Tables in markdown can be made with use of hyphens (---) and pipes (|). Namely +### Links: - | header1 | header2 | - | ------- | ------- | - | elem1 | elem2 | - | elem3 | elem4 | - -generates following table - -| header1 | header2 | -| ------- | ------- | -| elem1 | elem2 | -| elem3 | elem4 | - -### Images -Images can be included to the markdown page with use of the following syntax - - ![alternative text](path/to/the/image.png) - -For example: - -![cyrobek](images/CyRobek.png "load image to markdown file") - -### Other useful elements of markdown syntax - -___The basics of markdown syntax you will find here: [markdown basic syntax](https://www.markdownguide.org/basic-syntax/)___. \ No newline at end of file +The basics of markdown syntax you will find here: [markdown basic syntax](https://www.markdownguide.org/basic-syntax/). diff --git a/images/CyRobek.png b/images/CyRobek.png deleted file mode 100644 index d903a4d..0000000 Binary files a/images/CyRobek.png and /dev/null differ diff --git a/images/eclipse_logo.png b/images/eclipse_logo.png new file mode 100644 index 0000000..133e811 Binary files /dev/null and b/images/eclipse_logo.png differ diff --git a/mechanics/Completed_Chasis_Drawing_v1.pdf b/mechanics/Completed_Chasis_Drawing_v1.pdf new file mode 100644 index 0000000..66b4e66 Binary files /dev/null and b/mechanics/Completed_Chasis_Drawing_v1.pdf differ diff --git a/project_plan/project_charter.md b/project_plan/project_charter.md index 3e7fca9..0aaf245 100644 --- a/project_plan/project_charter.md +++ b/project_plan/project_charter.md @@ -1,36 +1,70 @@ -# A fancy titled project - Project Charter +# ECLIPSE - Project Charter ## Project description +The acronym ECLIPSE stands for rEmotely ControLled InsPection SystEm. -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Eget nunc scelerisque viverra mauris in aliquam sem. Nunc sed id semper risus in hendrerit gravida rutrum. Ultrices eros in cursus turpis massa. At risus viverra adipiscing at in. Posuere urna nec tincidunt praesent semper feugiat nibh. Nascetur ridiculus mus mauris vitae ultricies. Volutpat odio facilisis mauris sit amet massa vitae tortor condimentum. Fermentum odio eu feugiat pretium nibh ipsum consequat nisl. Luctus venenatis lectus magna fringilla. Feugiat in fermentum posuere urna. Nisl rhoncus mattis rhoncus urna neque viverra justo. Ultricies integer quis auctor elit sed vulputate. +## Project objectives -## Reasons for undertaking the project +The purpose of this project is to create a small, remotely controlled device with a gripping unit. The design should allow to work in harsh environment and places not accessible by human. -Arcu non sodales neque sodales. Accumsan in nisl nisi scelerisque eu ultrices vitae auctor. Pellentesque adipiscing commodo elit at imperdiet. Morbi blandit cursus risus at ultrices mi tempus imperdiet nulla. Neque gravida in fermentum et sollicitudin ac orci. Nisl nunc mi ipsum faucibus vitae aliquet nec. Tempor id eu nisl nunc mi ipsum. Tristique senectus et netus et malesuada. In hac habitasse platea dictumst quisque sagittis. Ultricies tristique nulla aliquet enim tortor at auctor. Diam quis enim lobortis scelerisque fermentum dui faucibus in ornare. Sagittis aliquam malesuada bibendum arcu vitae elementum. Dignissim convallis aenean et tortor. Eget mi proin sed libero. Id aliquet risus feugiat in ante metus. +## Success criteria -## Objectives of the project +- The robot should be able to go through a rectangular hole 50 cm wide and 50 cm tall. +- The robot should have a gripping unit that enables picking up and moving payload modelled as a paper cube 2x2x2cm. +- The robot does not stop on obstacles shorter than 5mm. +- The robot should be able to drive for 5 minutes continuously or stand 30 minutes in idle. -Id consectetur purus ut faucibus pulvinar elementum. Eu ultrices vitae auctor eu augue ut lectus. Mi bibendum neque egestas congue quisque egestas diam in arcu. Elit eget gravida cum sociis natoque penatibus et magnis. Est lorem ipsum dolor sit amet consectetur adipiscing. Malesuada fames ac turpis egestas maecenas pharetra. Etiam non quam lacus suspendisse faucibus interdum. Amet volutpat consequat mauris nunc. Fringilla urna porttitor rhoncus dolor purus. Libero nunc consequat interdum varius sit amet mattis vulputate. Risus viverra adipiscing at in tellus integer. Amet est placerat in egestas erat imperdiet. Accumsan sit amet nulla facilisi morbi tempus iaculis urna id. Phasellus egestas tellus rutrum tellus. Pharetra magna ac placerat vestibulum lectus. Parturient montes nascetur ridiculus mus. Consectetur adipiscing elit duis tristique sollicitudin nibh sit amet. +## Optional success criteria -## Constraints of the project +- The robot recognizes following objects: scissors, teddy bear, cup, fork, knife, spoon, bowl, bottle, mobile phone. +- The robot should withstand spraying it with water from distance of 20cm using water sprayer creating mist. -Vitae turpis massa sed elementum tempus egestas sed. Volutpat commodo sed egestas egestas. Non pulvinar neque laoreet suspendisse. In arcu cursus euismod quis viverra nibh cras. Enim neque volutpat ac tincidunt. Odio facilisis mauris sit amet massa. A erat nam at lectus. Nascetur ridiculus mus mauris vitae ultricies. At in tellus integer feugiat scelerisque. Cursus euismod quis viverra nibh. Curabitur gravida arcu ac tortor dignissim convallis. Dolor morbi non arcu risus. Aliquam etiam erat velit scelerisque. Pellentesque dignissim enim sit amet venenatis urna. Porttitor lacus luctus accumsan tortor posuere ac ut consequat. Eros in cursus turpis massa tincidunt dui ut. Neque viverra justo nec ultrices dui sapien eget mi. +## Main stakeholders and responsibilities -## Directions concerning the solution +- Jakub Kaszowski: Project leader, low level programming +- Paweł Rak: Mechanical and visual design +- Suheyla Keskin: Hardware development +- Mikołaj Pastucha: Remote control, video streaming +- Ryan Oliver Roberts: Computer vision -Dui id ornare arcu odio ut sem. Congue eu consequat ac felis donec et. Neque egestas congue quisque egestas. In dictum non consectetur a erat nam at. Rutrum quisque non tellus orci. Odio tempor orci dapibus ultrices in iaculis nunc sed. Varius vel pharetra vel turpis nunc eget. Porttitor rhoncus dolor purus non enim praesent elementum. Senectus et netus et malesuada. Arcu non odio euismod lacinia at quis risus sed vulputate. +## Risks identified early on -## Main stakeholders and responsibilities +The biggest risks in coresponding parts of the project: -- Student no. 1: responsible for the implementation of the algorithm solving problem -- Student no. 2: responsible for the design of the PCB and hardware -- Student no. 3: responsible for acquisition and handling sensor data +- Hardware: mistakes on PCB, availability of components. +- Software: C++, drivers unable to handle project requirements. +- Mechanical too weak motors/servos, electronics heating up. +- Computer vision: insufficient lighting, not enough computational power. +All of the section have common risks: -## Risks identified early on +- Under estimated effort of tasks + +## Risk mitigation + +| Risk | Solution | +| ----------------------------------------------------------------- | --------------------------------------- | +| Errors in hardware design | Using breakout modules and unversal PCB | +| Lack of necessary components | Buying components before making PCB | +| Groundbreaking problems with suspension | Drop the objective | +| Problems with remote control with game controller using bluetooth | Connect it to PC using cable | +| Not enough computational power for computer vision | Offload computations to PC | +| Drivers unable to handle project requirements | Modify objectives | +| Insufficient lighting | Embed LED strip in front of camera | + +## Projct milestones -Volutpat ac tincidunt vitae semper. Lorem mollis aliquam ut porttitor leo a diam. Euismod lacinia at quis risus sed vulputate odio ut enim. Fringilla ut morbi tincidunt augue interdum velit euismod. Phasellus vestibulum lorem sed risus ultricies tristique nulla aliquet enim. Massa sed elementum tempus egestas sed sed risus. Euismod elementum nisi quis eleifend quam adipiscing vitae proin sagittis. Sem nulla pharetra diam sit. Volutpat maecenas volutpat blandit aliquam etiam. Blandit turpis cursus in hac habitasse platea. Nisi scelerisque eu ultrices vitae auctor eu augue ut. Accumsan sit amet nulla facilisi. +1. The design of hardware is completed, software proof of concept is working (video streaming), design of chasis is completed. +2. The hardware is soldered and tested, software is partially completed (video streaming), mechanical elements are 3d printed and ready for assembly. -## Target project benefits +## Available resources -Turpis in eu mi bibendum neque. Neque viverra justo nec ultrices dui sapien. Risus sed vulputate odio ut enim blandit volutpat maecenas volutpat. Laoreet suspendisse interdum consectetur libero id faucibus nisl tincidunt. Sagittis purus sit amet volutpat consequat mauris nunc congue nisi. Mauris pharetra et ultrices neque ornare aenean euismod. Scelerisque mauris pellentesque pulvinar pellentesque. In hac habitasse platea dictumst quisque sagittis. Scelerisque varius morbi enim nunc faucibus a pellentesque sit. Scelerisque viverra mauris in aliquam sem. Tellus molestie nunc non blandit massa. Viverra accumsan in nisl nisi. \ No newline at end of file +| Resource | Source | +| ---------------------------------------- | -------------------------------------- | +| Mechanical chasis, suspension and wheels | 3D printer or off-the-shelf components | +| 1 standard CSI camera | Lab resources or electronic shop | +| LED strip | Electronic shop | +| PCB | jlcpcb | +| STM32F1 | Already owned | +| Raspberry Pi 4 | Lab resources or already owned | +| Xbox One game controller | Already owned | diff --git a/project_plan/project_tasks_n_schedules.md b/project_plan/project_tasks_n_schedules.md index f206c1b..4380741 100644 --- a/project_plan/project_tasks_n_schedules.md +++ b/project_plan/project_tasks_n_schedules.md @@ -1,45 +1,93 @@ -# A fancy titled project - Project Schedule +# ECLIPSE - Project Schedule ## Tasks - - Task 1: - - Task 2: - - Task 3: - - Task ...: - - Task 10: - - Task 11: + +### Low Level Software + +- Task 1: Project template for STM32 is setup +- Task 2: Driver for uart +- Task 3: Driver for servomechanism +- Task 4: Commands implementation +- Task 5: Bug fixing + +### Hardware +- Task 6: Determination of components and ordering +- Task 7: List of needed features of custom design PCB +- Task 8: Having list and schematic of elements of require power, selection of rechargeable battery and calculation of power consumption of each element due to time +- Task 9: Custom PCB and ordering +- Task 10: Powering mechanical and electronic elements and testing (before the PCB receive) +- Task 11: Check point and risk control of hardware elements, decision of backup plans +- Task 12: Soldering the elements on PCB and mechanical structure of the car +- Task 13: Problem solving and improving (time for adjustments) and in case of failing on any kind of the parts decisions of the backup plans + +### Software + +- Task 14: Consideration of the languages to be used +- Task 15: Selecting libraries +- Task 16: Creating the application in QT + - Creating the GUI + - Backend - creating a client on the PC to communicate over TCP/IP + - Installing the server on the RPI + - Decision on commands to be used for communication + - Downloading the on-board camera stream in near real time +- Task 17: Communication delay tests +- Task 18: Deployment of the application + +### Computer Vision + +- Task 19: Selection of model and dataset to be used +- Task 20: Testing Image Capture +- Task 21: first round of image captures for training +- Task 22: second round of image capture for training +- Task 23: camera calibration for precise tracking +- Task 24: First test of running script on RPI +- Task 25: error correction ## Milestones - - Milestone no. 1: SMART description of the milestone - - Milestone no. 2: SMART description of the milestone - - Milestone no. ...: SMART description of the milestone - - Milestone no. N: [Final presentation]: SMART description of the milestone + - Milestone no. 1: The design of hardware is completed, software proof of concept is working (video streaming), design of chasis is completed. + - Milestone no. 2: The hardware is soldered and tested, software is partially completed (video streaming), mechanical elements are 3d printed and ready for assembly. + - Milestone no. 3: Final presentation, project submission ## Gantt chart ```mermaid gantt dateFormat YYYY-MM-DD - title A fancy titled project - Gantt Chart + title ECLIPSE - Gantt Chart - section Tasks + section Low Level Software Task 1 :a1, 2023-10-01, 2023-10-15 Task 2 :a2, 2023-10-01, 2023-10-31 Task 3 :a3, 2023-11-01, 2023-11-19 Task 4 :a4, 2023-11-19, 2023-12-01 Task 5 :a5, 2023-12-02, 2023-12-10 - Task 6 :a6, 2023-12-10, 2024-01-01 - Task 7 :a7, 2024-01-02, 2024-01-16 - Task 8 :a8, 2024-01-17, 2024-01-31 - Task 9 :a9, 2024-02-01, 2024-02-15 - Task 10 :a10, 2024-02-16, 2024-03-01 - Task 11 :a11, 2024-03-02, 2024-03-16 + Task 6 :a6, 2023-12-10, 2023-12-20 + section Hardware + Task 7 :a7, 2023-10-10, 2023-10-26 + Task 8 :a8, 2023-10-10, 2023-10-26 + Task 9 :a9, 2023-10-26, 2023-11-05 + Task 10 :a10, 2023-11-05, 2023-11-23 + Task 11 :a11, 2023-11-23, 2023-11-30 + Task 12 :a12, 2023-11-23, 2023-12-09 + Task 13 :a11, 2023-12-09, 2023-12-16 + section Software + Task 14 :a11, 2023-10-10, 2023-10-26 + Task 15 :a11, 2023-10-10, 2023-10-26 + Task 16 :a11, 2023-10-26, 2023-11-30 + Task 17 :a11, 2023-11-30, 2023-12-09 + Task 18 :a11, 2023-11-30, 2023-12-09 + section Computer Vision + Task 19 :a11, 2023-10-05, 2023-10-10 + Task 20 :a11, 2023-10-10, 2023-10-15 + Task 21 :a11, 2023-10-15, 2023-10-20 + Task 22 :a11, 2023-10-20, 2023-10-30 + Task 23 :a11, 2023-10-30, 2023-11-05 + Task 24 :a11, 2023-11-05, 2023-11-08 + Task 25 :a11, 2023-11-08, 2023-11-11 + Task 26 :a11, 2023-11-11, 2023-11-15 section Milestones - Milestone 1 :m1, after a2, 2023-10-31 - Milestone 2 :m2, after a4, 2023-12-01 - Milestone ... :m3, after a7, 2024-01-16 - Milestone N :m4, after a11, 2024-03-16 -``` - - -More about how to make a gantt chart in mermaid, you will find here: [Mermaid Gantt](https://mermaid.js.org/syntax/gantt.html) \ No newline at end of file + Milestone 1 :m1, after a9, 2023-11-05 + Milestone 2 :m2, after a12, 2023-12-09 + Milestone 3 :m2, 2024-01-17, 2024-01-17 +``` \ No newline at end of file diff --git a/report/Makefile b/report/Makefile new file mode 100644 index 0000000..54fb6d5 --- /dev/null +++ b/report/Makefile @@ -0,0 +1,24 @@ +SHELL = /bin/sh + +FILE0 = document +TEX = $(FILE0).tex +XDV = $(FILE0).xdv +PDF = $(FILE0).pdf + +all: + make tex + +tex: + xelatex -no-pdf $(TEX) + # xdvipdfmx.exe $(XDV) + xelatex -synctex=1 -interaction=nonstopmode $(TEX) + make clean + +pw: + zathura document.pdf & + +help: + echo "USAGE: make [all/tex/pw/clean]" + +clean: + rm -f *.aux *.dvi *.idx *.ilg *.ind *.log *.nav *.out *.snm *.xdv *.toc *~ diff --git a/report/document.pdf b/report/document.pdf new file mode 100644 index 0000000..0d1e70c Binary files /dev/null and b/report/document.pdf differ diff --git a/report/document.tex b/report/document.tex new file mode 100644 index 0000000..8fe4f43 --- /dev/null +++ b/report/document.tex @@ -0,0 +1,1220 @@ +\documentclass[12pt]{article} +\usepackage{graphicx} +\usepackage[hidelinks]{hyperref} +\usepackage{listings} +\usepackage{multicol} +\usepackage{caption} +\usepackage{listings,lstautogobble} +\usepackage{xcolor} +\usepackage{pdfpages} +\usepackage{enumitem} + +\usepackage{fontspec} +\setmainfont{Times New Roman} +\graphicspath{ {img/} } + +\usepackage[a4paper, margin={0.7in, 0.7in}]{geometry} + +\usepackage{fancyhdr} + +\def\thetitle{Remotely Controlled Inspection System} +\pagestyle{fancy} +\fancyhead{} +\renewcommand{\headrulewidth}{0pt} +\fancyfoot[L]{Wrocław, 2024} +\fancyfoot[C]{\thetitle} +\fancyfoot[R]{\thepage} +\renewcommand{\footrulewidth}{0.5pt} + +\definecolor{codegreen}{rgb}{0,0.6,0} +\definecolor{codegray}{rgb}{0.5,0.5,0.5} +\definecolor{codepurple}{rgb}{0.58,0,0.82} +\definecolor{backcolour}{rgb}{0.95,0.95,0.92} + +\lstdefinestyle{CStyle}{ + backgroundcolor=\color{backcolour}, + commentstyle=\color{codegreen}, + keywordstyle=\color{magenta}, + numberstyle=\tiny\color{codegray}, + stringstyle=\color{codepurple}, + basicstyle=\ttfamily\footnotesize, + breakatwhitespace=false, + breaklines=true, + captionpos=b, + keepspaces=true, + numbers=left, + numbersep=5pt, + showspaces=false, + showstringspaces=false, + showtabs=false, + tabsize=2, + frame=single, + language=C++ +} + +\newcommand{\image}[3]{ +\begin{figure}[h] + \begin{center} + \includegraphics[scale=#3]{#2} + \end{center} + \caption{#1} +\end{figure}} + +\usepackage{tocloft} +\renewcommand{\cftsecleader}{\cftdotfill{\cftdotsep}} + +\begin{document} +\begin{titlepage} + \begin{center} + \includegraphics[scale=0.3]{img/pwr.png}\\ + \vspace{20pt} + \textbf{Laboratory of Optoelectronics and Photonics} \\ + \textbf{Wrocław University of Science and Technology} + \\ + \textbf{Chair of Electronic and Photonic Metrology} + + \vspace{20pt} + + \textbf{\huge\thetitle} \\ + \vspace{5pt} + \Large Advanced Robotics Project \\ + \vspace{20pt} + \normalsize + + \begin{tabular}{ |c|c|c| } + \hline + Name & Surname & Album number \\ \hline + Jakub & Kaszowski & 263544 \\ \hline + Mikołaj & Pastucha & 264353 \\ \hline + Paweł & Rak & 264355 \\ \hline + Suheyla & Keskin & 269478 \\ \hline + Ryan & Roberts & 269580 \\ + \hline + \end{tabular} \\ + \vspace{5pt} + Wrocław, 2024 \\ + \end{center} +\end{titlepage} +\newpage +\tableofcontents{\thispagestyle{fancyplain}} +\newpage + +\section{Introduction} +% Subject of the report, content of the report +The ECLIPSE project aims to create a remotely controlled inspection system +capable of operating in harsh and inaccessible environments. + +In the face of a rapidly evolving technological landscape, there is an urgent +need to develop innovative solutions capable of overcoming the challenges of +harsh environmental conditions and hard-to-reach spaces. The ECLIPSE project, +in other words, is an academically-driven initiative aimed at revolutionising +inspection processes through the development of a compact and flexible device: +the Remote Controlled Inspection System. + +The acronym 'ECLIPSE' heralds the main idea of the project - rEmotely +ControLled InsPection SystEm (Remotely Controlled Inspection System). The main +objective of the project was to develop a small but highly effective device +equipped with an advanced grasping unit, for operation in harsh conditions and +areas inaccessible to humans. + +This academic initiative sets clear objectives: to push the boundaries of +inspection capability, using remote control technology and implementing a +robust gripping mechanism. This text constitutes a comprehensive documentation +of the ECLIPSE Project. + +\subsection{System Overview} + +\subsubsection{Conceptual Framework} + +The ECLIPSE remotely controlled inspection system is ingeniously designed to +tackle the challenges of maneuvering through environments that are either +difficult for humans to access or pose potential risks. +The core pillars of exploration, manipulation, and adaptability drive the +system, revolutionizing robotic inspections in confined and demanding spaces. + +\vspace{1cm} +\noindent Key Aspects of the Conceptual Framework: +\begin{itemize} + \item Exploration and Inspection: ECLIPSE is tailored to navigate confined + spaces, traverse challenging terrains, and perform inspections where human + access is limited or unsafe. + \item Manipulation: Featuring a manipulator, the system excels at interacting + with its surroundings. This capability allows it to execute tasks such as + retrieving small objects or adjusting its orientation for optimal exploration. + \item Real-time Control: The system is remotely operated through a dedicated + Python application on a PC. This application establishes a socket connection + with a server hosted on a Raspberry Pi (RPI), enabling real-time interaction + and seamless control. +\end{itemize} + +\newpage + +Functionalities: + +\begin{enumerate}[label=\alph*)] + \item Remote Control and Video Streaming: + + The Python-based application on the PC facilitates remote control, offering + users an intuitive interface for navigation. + Real-time video streaming enhances situational awareness, empowering operators + to make informed decisions during exploration. + \item Motor and Servo Control: + + The RPI server acts as an intermediary, forwarding commands from the PC + application to the HAT (Hardware Attached on Top) via a UART port. + The HAT, a custom PCB, receives and interprets these commands, orchestrating + precise control over motors and servos for terrain adaptation and manipulation + tasks. + \item Autonomous Object Recognition: + + Integrated computer vision, employing the YOLO-v8 model, endows the robot with + the capability to autonomously recognize common objects in its environment. + Component Interdependencies: +\end{enumerate} + +The operational harmony of ECLIPSE relies on the seamless coordination between +its hardware components and software modules. + +The PC application, written in Python, serves as the user interface and remote +control hub. +Communication flows through a socket connection from the PC application to a +server hosted on the Raspberry Pi. +The Raspberry Pi, in turn, acts as a bridge, forwarding messages to the HAT +through a UART port on the custom PCB. +The HAT, equipped with an STM32F103C8T6 microcontroller, efficiently manages +low-level tasks, including motor and servo control. +Meanwhile, the camera system operates independently, directly connected to the +Raspberry Pi through MMAL, ensuring a dedicated focus on capturing visual data +during the exploration process. + +\vspace{1cm} +\image{System overview.}{diagram.png}{0.4} +\newpage +\subsection{Client Application Overview} +\subsubsection{User Interface Design} + +The client application serves as the user's primary interface for interacting +with the ECLIPSE remotely controlled inspection system. The design philosophy +prioritizes user-friendliness, efficiency, and real-time feedback. + +Key features include: +\begin{itemize} + \item Intuitive Navigation: The user interface provides intuitive controls + for remote navigation, ensuring a seamless experience for operators. + \item Video Streaming: A real-time video stream from the robot's perspective + enhances situational awareness, enabling precise control and decision-making. + \item Control Panels: The application includes dedicated control panels for + motor and servo manipulation, allowing users to adjust parameters with ease. + \item Object Recognition Display: Autonomous object recognition results are + displayed in real-time, providing valuable information about the environment. +\end{itemize} + +\subsubsection{Functionality Integration} +The client application is intricately connected to the overall system +functionalities, contributing to the seamless operation of ECLIPSE: + +Remote Control: Users can navigate the robot remotely through the client +application, ensuring precise and responsive control. +Live Video Feed: The video stream enhances the operator's understanding of the +robot's surroundings, promoting effective exploration and inspection. +Autonomous Object Recognition Interaction: Users receive real-time updates on +object recognition, allowing for informed decision-making during autonomous +operations. + +\subsubsection{User-Centric Features} +To enhance the user experience, the client application includes several +user-centric features: + +Responsive Design: The application is designed to be responsive, ensuring +usability across various devices and screen sizes. +Error Handling: User-friendly error messages and alerts are implemented to +guide operators in case of communication issues or system errors. +Feedback Mechanisms: The application incorporates feedback mechanisms, +providing operators with insights into the robot's status and actions. + +\subsection{Team structure} +The team is structured as follows: +\begin{center} + \begin{tabular}{|c|c|} + \hline + Scope & Member \\ \hline + Mechanics & Paweł Rak \\ \hline + Hardware & Suheyla Keskin \\ \hline + Low level software & Jakub Kaszowski \\ \hline + Software & Mikołaj Pastucha \\ \hline + Computer vision & Ryan Oliver Roberts \\ \hline + \end{tabular} +\end{center} +Each person is responsible for their section. Once completed, it was integrated +with +the rest. + +\newpage +\section{Software} +The ECLIPSE project aims to create a remotely controlled inspection system +capable of operating +in harsh and inaccessible environments. This section focuses on the +implementation of remote control functionality +and video streaming for real-time monitoring. +\vspace{10pt} + +\noindent Objectives: +\begin{itemize} + \item Implement a reliable remote control system for device manipulation. + \item Develop a video streaming solution to enable continuous monitoring in + real-time. +\end{itemize} + +\subsection{Remote Control Implementation} + +\subsubsection{Communication Protocol} +For remote control, we selected the TCP/IP +communication protocol. This protocol was chosen due to its reliability, +ability to operate over large distances, and support for inter-process +communication. TCP/IP, being the foundation of the internet, is a proven and +reliable protocol that enables communication between various devices on the +network. + +Compared to other protocols such as IPX/SPX used by Netware, TCP/IP offers +greater universality and is widely supported across various platforms and +devices. IPX/SPX, although once popular, is now rarely used and does not offer +the same level of support as TCP/IP. + +TCP/IP facilitates seamless communication between the client application and +the Raspberry Pi, enabling precise control of the inspection device. The client +(controlling application) and the server (Raspberry Pi) communicate with each +other using sockets, which are an application programming interface for TCP/IP. +The client sends requests to the server, and the server responds to these +requests, enabling interactive control of the device. + +After sending the message over the TCP/IP network, the message is then sent to +the UART port on the Raspberry Pi. UART (Universal Asynchronous +Receiver/Transmitter) is a hardware communication interface used for +transmitting data between devices. In the case of the Raspberry Pi, UART is +employed for communication with various devices, including motor controllers +and servos. The messages received by the Raspberry Pi are structured as Python +dictionaries, providing instructions for both motor and servo control. + +\subsubsection{Motor Control} +Motor control commands are conveyed through Python dictionaries, with each +command specifying the direction and speed for each motor. The key in the +dictionary represents the movement direction ('w' for forward, 's' for +backward, 'a' for left, 'd' for right), and the corresponding value is a list +of two numbers representing the speed for each of the three motors on both +sides. For instance: + +'w': [10, 10] signifies that all motors should move forward at a speed of 10. +'a': [-5, 5] implies that the motors on one side should move forward at a speed +of 5, while the motors on the other side should move backward at a speed of 5, +resulting in a left turn. +These commands provide granular control over the movement of the inspection +device, allowing for precise navigation in various environments. + +Servo Control: +Servos play a crucial role in controlling the orientation of the inspection +device, particularly the camera. Commands for servo control are also structured +as Python dictionaries. The key in the dictionary signifies the action, such as +'rotate\textunderscore camera,' and the corresponding value specifies the angle +or movement. +The specific format for a servo control command might look like: + +'CMD,S,1,90': This command instructs the system to adjust Servo 1 to an angle +of 90 degrees. +The servo control commands are designed to be flexible, allowing operators to +adjust the orientation of servos dynamically during the remote inspection +process. The integration of servos enhances the system's versatility, enabling +it to adapt to different scenarios and capture a comprehensive view of the +inspection environment. + +This comprehensive command structure ensures effective communication between +the remote control system and the Raspberry Pi, facilitating seamless control +over both motors and servos during the inspection process. + +Sample Python code for communication initialization: +\begin{lstlisting}[style=CStyle,language=Python] +import socket + +def initialize_connection(): +    host = 'your_remote_device_ip' +    port = 12345 + +    try: +        client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +        client_socket.connect((host, port)) +        return client_socket +    except Exception as e: +        print(f"Error initializing connection: {e}") +        return None + +# Sample code for sending a command +def send_command(command, client_socket): +    try: +        client_socket.sendall(command.encode()) +        print(f"Command sent: {command}") +    except Exception as e: +        print(f"Error sending command: {e}") + +# Usage example +connection = initialize_connection() +if connection: +    send_command("CMD,MOVE_FORWARD", connection) + +\end{lstlisting} +\subsubsection{User Interface} +The User Interface (UI) for the remote control system has been meticulously +designed and implemented using the PyQt5 framework, a set of Python bindings +for Qt libraries which are used to create cross-platform applications. The +primary goal of the UI is to provide a seamless, intuitive, and user-friendly +control experience for operators overseeing the inspection device. +The UI is encapsulated within the ClientApp class, which extends the PyQt5 +QWidget class to create a standalone application. This encapsulation ensures a +clean and organized codebase, promoting maintainability and scalability of the +system. +Upon launching the application, users are presented with a well-organized +interface that balances functionality with clarity. The design adheres to +modern UI/UX principles, ensuring that operators can easily navigate and +control the inspection device without extensive training. + +At the core of the UI is a real-time video feed displayed in the +image\textunderscore label +widget. This visual representation ensures that operators have immediate access +to the device’s surroundings, enhancing situational awareness during remote +control operations. This is crucial in environments where real-time response is +necessary. +The control panel features an informative status bar (connection\textunderscore +status) +indicating the current connection status with the video stream. This allows +operators to monitor the connection status and ensure that the control commands +are being transmitted without interruption. +The UI further incorporates a speedometer (speedometer) to provide a visual +representation of the device’s speed. This real-time feedback aids operators in +making precise adjustments and maintaining the desired speed, enhancing the +accuracy and efficiency of the inspection process. +To streamline user interaction, a set of control instructions is presented in +the instructions\textunderscore label. This quick reference guide helps +operators understand +the control scheme, reducing the learning curve and enhancing user experience. +Key functionalities, such as increasing or decreasing speed and turning left or +right, are mapped to intuitive keyboard commands (W, S, A, D), ensuring a +straightforward control scheme. +Additionally, a “Rotate Frame” button (rotate\textunderscore button) has been +implemented to +toggle the rotation of the displayed video frame. This feature provides +flexibility in adapting to different orientations of the inspection device, +accommodating various operational scenarios and user preferences. +The UI is not only responsive to user inputs but also serves as a feedback +mechanism. Error messages are displayed in real-time in a dedicated log area +(log\textunderscore text\textunderscore edit), notifying operators of any +issues such as connection errors or +frame reading failures. This proactive error handling enhances system +reliability and allows for quick troubleshooting. +\image{Graphical User Interface for remote control.}{gui.png}{0.8} + +\subsection{Video Streaming Implementation} + +\subsubsection{Libcam integration} +The integration of libcam, a versatile command-line tool for capturing and +streaming video, serves as a pivotal element in achieving seamless and +high-quality video streaming within the ECLIPSE project. This tool was +judiciously selected and integrated into our system to cater to the unique +requirements of remotely controlled inspections, thereby ensuring that the +system is equipped with the necessary capabilities to handle the complexities +of real-time video streaming. + +The bash script, aptly named stream.sh, orchestrates the execution of libcam +with specific parameters tailored to the project’s needs. This script is +configured to run indefinitely, thereby ensuring uninterrupted video capture +from the device’s camera. The parameters such as --width, --height, and +--framerate are meticulously set to a resolution of 1920x1080 and 30 frames per +second. This configuration ensures optimal video quality and fluidity, which +are crucial for maintaining the integrity of the inspection process. + +The --listen flag plays a significant role in this setup. It is instrumental in +establishing a continuous video stream by creating a persistent connection for +real-time monitoring. This feature is particularly beneficial in scenarios that +require long-duration inspections or when the inspection device is navigating +through extensive structures. + +The integration of libcam not only streamlines the video capture process but +also lays the foundation for further optimization. It opens up possibilities +for enhancements such as adaptive bitrate streaming or the integration of +advanced video codecs, which could further improve the efficiency and quality +of the video stream. + +By harnessing libcam’s capabilities, we have a robust and reliable solution for +video streaming that aligns perfectly with the project’s objectives. This +seamless integration significantly contributes to the overall success of the +ECLIPSE project. It enhances the remote inspection system’s capabilities, +enabling it to operate effectively even in challenging and inaccessible +environments. +\image{Video Compression.}{compression.png}{1.2} + +\subsection{Testing and Optimization} +Thorough testing was conducted to assess the video streaming performance under +diverse conditions. The testing scenarios included varying network conditions, +different video resolutions, and multiple concurrent connections. Based on the +test results, several optimizations were made to enhance streaming efficiency. +These included adjusting the video bitrate according to network conditions and +implementing a buffering strategy to handle network latency. + +\subsection{Challenges and Solutions} +Throughout the implementation, several challenges were encountered. One of the +main challenges was ensuring a stable and high-quality video stream under +varying network conditions. This was addressed by implementing adaptive bitrate +streaming in the libcam configuration. Another challenge was handling multiple +concurrent connections without compromising the video quality. This was +overcome by implementing a queue-based system to manage the connections. + +\subsection{Results and Performance} +The remote control and video streaming components have demonstrated excellent +performance. The system was able to maintain a stable video stream with a +latency of less than 200ms under optimal network conditions. The responsiveness +of the remote control was also exceptional, with commands being executed with +minimal delay. + +\newpage +\section{Hardware} +This part of the report describes how the hardware part of the project was +done. + +\subsection{Components selection} +\subsubsection{Remote control} +In order to control the robot remotely, some sort of wireless communication +solutions was needed. +We have decided to use Raspberry Pi 4 with 8GB memory. The biggest advantages +is the availability, price, +good documentation online and the fact that we have already one. +This SoC runs linux, therefore providing us with a complete operating system +with drivers. That enabled us to develop software easily, +using python and its powerful libraries, like OpenCV. +However, there are disadvantages of using Raspberry Pi. +Its processor was not designed to be a robot controller. Thus, it does not have +enough of needed peripherals. For example, it only has 2 PWM channels, whereas +for +6 motors + 4 servos, we need more than that. + +\subsubsection{The HAT} +Popular solution to enhance the possibilities of RaspberryPi is to use so +called 'HATs' (Hardware Attached on Top). +The Raspberry Pi boards come with 40W GPIO headers (Model B+ and onwards) that +have been designed specifically with add-on boards in mind. +Some of popular HATs can power up the board or provide more interfaces. +However, we could not find any HAT that meets our needs. Therefore, we decided +to make one ourselves. + +The tasks of our HAT are: +\begin{itemize} + \item Power the RPi and other components from the battery. + \item Embed a MCU, capable of communication with RPi and generating PWM + signals. + \item Embed an H-Bridge for controlling the motors. + \item Provide a convenient way to connect motors and servos. +\end{itemize} + +\image{Example of RaspberryPi HAT.}{rpihat1.png}{0.2} + +\subsection{MCU selection} +The main criteria for MCU selection were: +\begin{itemize} + \item Amount of PWM channels. + \item Communication peripherals (UART with DMA preferred). + \item Experience of team members. +\end{itemize} +The selected MCU is STM32F103C6T6, that can be found onboard breakout module +Bluepill. + +With the complexity of an Cortex M4 core, the manual configuration of every +peripheral and clock using registers is pretty tedious and error prone. In +order to write a portable +code, the Hardware Abstraction Layer libraries from the manufacturer were +used. They significantly speed up the process of writing hardware drivers and +lets us focus +on the algorithm and achieving requirements. Moreover, the graphical tool +lets us generate appropriate code for setting proper settings of peripherals +and clocks. +A very useful feature of all arm microcontrollers is SysTick interrupt +\cite{stm32reference}. It is called each millisecond and increments a time +variable. +It enables us to measure time easily, without setting up a dedicated timer. + +Another extremely useful tool from a perspective from hardware perspective is +the availability of Cube MX configuration tool, that enables to easily plan the +function +of specific pins of a microcontroller and seeing the results in a graphical +environment, with automatic error checking. +\image{Cube MX visual configuration tool, used to plan the usage of MCU + pins.}{cubemx.png}{0.32} +\newpage +\subsection{Power supply} +Once the components were selected, the next part was to design a reliable power +section capable of powering all of the devices. +The input voltage from the battery is 7.4V. The MCU needs 3.3V and the RPi +needs around 5V. Similarly, the servos need to be powered with 5V. + +Therefore, 3 power sections are needed: +\begin{enumerate} + \item Output Voltage: 3.3V, Purpose: power STM32 + \item Output Voltage: 5V, Purpose: power RPi + \item Output Voltage: 5V, Purpose: power servos +\end{enumerate} + +With voltage drop of 2.5V to 4V and requirement to power the setup from the +battery, using a voltage stabilizer was not really an option. +These devices would provide stable and lower voltage, but would loose to much +energy on generating heat. +In order to drop down voltage with higher efficiency, a DC-DC buck converter +was used. + +\subsection{PCB routing} +Having decided to power everything from battery through DC-DC converters, an +important part was to isolate the powersections from each other so that the EMI +are not a problem. With our original plan to make a HAT, the PCB would have to +be small enough to fit on top of RPi. It quickly proved to be impossible using +only 2 layered board. Instead of deciding to change to 4 layered board, we have +decided to make a motherboard in which the RPi will plugged in, rendering it +almost same as HAT, but with more space to route signals. + +\image{Layout of the final PCB.}{pcblayout.png}{0.4} + +\newpage +\subsection{PCB soldering} +Soldering was done in a student's club room, equpped with soldering iron, hot +plate and hot air. + +\image{Soldered board with RPi plugged in.}{board1.png}{0.08} + +\subsection{PCB issues} +The main issue with the PCB layout is wrong footrpint of the RPi and missing +capacitors. + +During initial stages of development, the HAT was supposed to sit on top of +RPi. The the custom footprint +was made having that in mind. Once the idea was changed, from making HAT to a +motherboard with plugged in RPi, +the footprint was not adjusted. The fix for that wa to cut some pins (the used +and conflicting ones) and connect the rest of them with wires. + +The other issue was that the board suddenly stopped working, after few minutes +of being powered from external power supply +In practice, it turned out that DC-C converters generate a lot of noise on the +input. In our case the noise got in phase and burned the DC-DC converters. +Fortunately, we bought more of them (twice the needed amount). After adding +additional capacitors, the board works flawlessly. + +\image{Fixed footprint with hand soldered wires.}{boardfootprint.png}{0.08} +\newpage +\section{Low level software} +As mentioned in the hardware part, the main MCU for our motherboard was +selected to be STM32F103C8T6. +Such selection allowed us to work on the code before the final prototype was +made, as the same MCU +can be found in Bluepill evaluation kit. + +The main tasks of the MCU are: +\begin{enumerate} + \item Receive commands from RaspberryPi. + \item Deserialize commands. + \item Control motors and servos. + \item Handle errors. + \item Implement safety features. +\end{enumerate} + +\subsection{Toolchain selection} +The STM32 can be programmed using both C and C++. The ARM company provides +fork of gcc for the Cortex M4 cores that are used in the Blackpill, which use +C++ 17 standard. +We have decided to use STM32CubeIDE. It is an Eclipse based IDE that comes +with proper compiler and visual configurator of the peripherals and clock. + +With the complexity of an Cortex M4 core, the manual configuration of every +peripheral and clock using registers is pretty tedious and error prone. In +order to write a portable +code, the Hardware Abstraction Layer libraries from the manufacturer were +used. They significantly speed up the process of writing hardware drivers and +lets us focus +on the deserialization and implementing business logic. Moreover, the +graphical tool lets us generate appropriate code for choosing proper settings +of clocks and checks for errors. + +The best approach turned out to be separate the peripherals configuration +(written in C) from algorithm (written in C++). The only place of connection is +when the C code detects +a communication frame and calls a proper C++ function for further data +manipulation. + +% A very useful feature of all arm microcontrollers is SysTick interrupt \cite{stm32reference}. It is executed in one millisecond interval and increments a time variable. +% It enables us to measure time easily, without setting up a dedicated timer. I + +\subsection{Peripherals configuration} +The selected microcontroller has a powerful set of peripherals with addition +of DMA, capable of making data transfers between peripherals and memory without +core supervision.\\ + +\noindent The most important peripherals for our project are: +\begin{itemize} + \item timer - for creating PWM signal, + \item serial port - for communication wit RPi, + \item ADC - for optional measurements of battery voltage. +\end{itemize} + +The timers for generating the PWM signals require very little configuration. +After configuring the clocks, the capture-compare PWM mode has to be selected +and proper values +of counter and overflow value has to set. With such setup, in order to change +the duty factor, it is enough to jest change a value of one register. +In order to generate a suitable signal for servomechanisms, proper values +were selected to create pulse with length between 10 and 50 milliseconds. + +\subsection{Servo control} +According to the datasheet, a servomechanism should be driven by a PWM steering +signal with +period of 20ms and duty cycle between 1ms (0 degrees) and 2ms(180 degrees). +In practice, servos behave unpredictable. Some of the have different +boundaries, +some of them did not behave well under load of the arm. + +The solution to make the servo movements portable was to calibrate each of them +when the robot was assembled. +Having the calibration numbers, the desktop client app was adjusted so that it +sends the position within those boundaries, +set for each servo separately. + +\subsection{Command parser} +One of the hardest part of such project is to write a command parser in clear +and bug free way. +Usually in the embedded field, the software is written in C, using +\textit{string.h} library. +However, the code writen using these C style functions significantly lack +clarity. +In order to improve the readability and maintability of the parser, it was +written with C++ and Embedded Template Library. + +The ETL provides a set of useful templates for +working with string. It can be used in place of the STL on low spec systems +as it does not require dynamic memory allocation - everything has to be +allocated at compile time. +Under the hood, still the same functions from \textit{string.h} are called, +but the C++ provides a better interface. +Moreover, it prevents from accidential buffer overflows by implementing for +additional checks for the string length and buffer size. + +\subsection{Safety features} +The most important safety feature is automatic break that engages +automatically if no command was received for a period of time. Such mechanism +protects the robot from running away +in case the communication if the communication is lost. + +Another mechanism is protection of motors. Their operational voltage is equal +to 5V, but the H-Bridge is capable of supplying up to 7.5 volts. In order to +prevent too high voltage +being applied to the motor, a software switch is present that limits the +maximum voltage. + +\subsection{Unit testing} +In order to make sure that the commands are parsed properly, unit tests were +made using Google Test library. +To be able to run the parse on host PC, an additional cmake project was set up. +The file \textit{user\textunderscore logic.cpp} contains a part that is +included depending on whether a macro HOST\textunderscore BUILD is present. +When compiled for the STM32, platform specific header files are included and a +set of macros are defined. These macros provide an interface between logic and +underlying hardware. + +On the other hand, if compiling for PC, a set of static variables are defined. +Moreover, the set of generated macros instead of controlling the memory mappeda +peripherals, changes the aforementioned static variables. + +\newpage +\section{Mechanics} +Main idea of the ECLIPSE has grown from a need of inspecting, or exploring +environments potentially inaccessible or even hazardous for human beings. Two +main requirements were defined for the system to be met. To inspect, and +manipulate the environment, and to be able to traverse it properly. As the +resources were scarce, and development time extremely limited, I decided to +outsource the manipulator. The main focus was developing a platform +capable of traversing rough terrain easily. + +\subsection{Tools} +\subsubsection{CAD Software} + +To accomplish sophisticated 3D modeling I needed a more sophisticated set of +programs. AutoCAD, the only cad software taught during the studies, is +preferred for 2D parametric drawings, and is not really suitable for complex +shapes. Overall the software is too slow, and it lacks anything other than +basic and painful solid modeling. At the beginning of the project I started +research about cad software available for student educational license. The most +popular software on the market are Dassault Solidworks, and Autodesk Inventor. +Both of those programs have one thing in common, their development started over +20 years ago and because of compatibility, and old core design choices are a +bit obsolete in my opinion; However I was able to find two quite recent +developments Siemens Solid Edge, and Autodesk Fusion 360. Both of those +programs are cloud based, parametric design cad software with new modeling +techniques and integrated AI. For the purpose of the project I decided to start +learning the fusion 360. Most important advantages for choosing the fusion +were: Top to bottom, and bottom to top assemblies, solid, surface and mesh +modeling. Also the autodesk license was easier for me to obtain because of +previous use of their software. Program itself is quite intuitive but totally +different from AutoCAD I was very familiar with. I did not have enough time for +a proper introduction, or lengthy learning process so I rushed through a “Learn +the basics of Fusion 360” course in 4 days. Starting with the course was a very +wise idea because I learned good practices and industry standards essential for +more complex projects. Without this experience, fixing some problems that +occurred later in development would take triple the time. Overall learning the +Fusion was a very good choice, as I use it on a daily basis in every hobby or +project. + +\subsubsection{Slicing Software} + +As the 5th semester of ECE is extremely project focused and time limited I +decided to buy my own 3D printer for a quicker development. As the manufacturer +of my 3D printer did not include a proper slicing software with the printer, I +had to choose one myself. As I did not have enough time to fiddle a lot with +the setting or Gcode I have selected Ultimaker Cura as my go to slicing +program. The most essential part of Cura is its very easy construction, and +pop-ups explaining with detail every single setting. Program itself is very +intuitive, and with a ready made preset for my printer I could instantly start +testing what settings impact the printing quality the most. With over 70 hours +of printing required to finish all prototypes and printing of the parts itself +I cannot really say a bad word about the software. +\image{Sliced part of a robot.}{part.png}{0.5} + +\subsection{The Gripper} +As mentioned above, the entire design of the gripper was borrowed from the +sketchfab. Originally the manipulator was a 5 dof design, with 6 servos of two +different types. We decided that We did not have enough time to develop inverse +kinematics for a 5 dof arm, or enough budget to spend over 200 pln for servos +alone. Decision was made, so I modified the files to fit the project, by +removing 3 big expensive servos, and leaving only 2 dof of rotation, and +up/down, and of course opening and closing of the gripper. After a bit of +re-modelling I managed to make the design small, and cheap enough for the +purpose of the ECLIPSE. Gripper assembly is entirely 3D printed from a PLA +filament, and assembled using M3 ISO flathead bolts and nuts. + +\image{Rendered gripper in CAD software.}{gripper.png}{0.4} + +\subsection{The Chassis} +Designing and building a completely custom all-terrain platform for the +inspection system was the main focus of the mechanical part of the project. As +a team We were interested in a practical design, and most of the lab-available +platforms were not really worthy of crossing a high doorstep, not to mention a +staircase. To fulfill the requirement of of-roadworthiness, high ground +clearance and ability to keep all the wheels on the ground was essential for +the project success. What is more, the mechanical part needed to be sturdy and +reliable to be able to function in those environments without a constant need +of repair. + +\subsubsection{Suspension Design} + +As the available engines are weak, and of bad quality, suspension does not need +to provide high, or even low speed damping. With a top speed of 10 km/h shock +absorption or handling were irrelevant for the design. To maximize the ground +clearance and the ability to keep all the wheels on the ground I have chosen +the proven Rocker-Bogie type suspension. I was mainly inspired by NASA Mars +rovers like Curiosity, and Perseverance and their ability to cross extreme +terrain. For a compromise between high ground clearance and great stability, I +have chosen the angle of 120 degrees between the rocker arms. I opted for +engine-in-arm design, so long engines determined the minimum length of the +rocker to be 186 mm. It is quite much bigger than I liked, but there was no +other budget engine option. Because of that the arbitrary goal of system length +shorter than 350 mm could not be met. Current design of the suspension allows +approach and departure angles to be over 90 degrees. + +\subsubsection{Electronics Containment Unit} + +At the start of the design work We decided that all the fragile electronics +should be contained in a sturdy and rain proof container. DC motors itself were +not really a problem, as those should be able to function underwater if the +contact pins, and wires were properly isolated. Also with the engine-in-arm +design and motors integrated with the transmission, electronics components are +located very high in the design. To properly control the entire design, the +main PCB needs to communicate with 6 engines and 4 external servos. To make the +wires safe, We used industrial grade heat shrinks. To make all the connections, +and wire cutouts water tight, hot glue was used. Main compartment was designed +with Li-on cells in mind. Because of the dangerous nature of those cells, walls +of the containment unit are over 4 mm thick, with 6 mounting screws, and TPU +gasket providing a proper seal. To safely fix all the electronics inside the +containment unit, threaded brass inserts, and proper mounts were used. All +important screw connections include threaded inserts, which allow quick and +painless disassembly without losing the properties of the connection. Overall +we ended up with a very rigid, sturdy structure which phenomenally works as the +mounting platform of suspension, gripper, and all additional equipment. + +\subsubsection{Main Bearings and screws} + +To increase longevity, and greatly decrease the friction of rotating joints +high quality ball bearings were used. Double for every single joint. To +guarantee the reliability of all threaded connections, a blue threadlock was +used on all the important connections. + +\subsection{Challenges and solutions} +The biggest problem encountered during the development of the mechanical part +was unfortunately the problems with cheap parts, or rather their documentation. +Almost 20 hours of redesign work were needed to fix the problem with improper +physical documentation of the engines. If I received the correct documentation, +or physical engine in the beginning of the mechanical work, when I had enough +time to work on the project constantly, the entire mechanical part would be +finished and assembled in early december. + +\newpage +\section{Computer vision} +\subsection{Overview on Computer Vision} +Computer Vision (CV) is a field of study that enables machines to interpret and +understand visual information from the world. It has found numerous +applications, one of which is in the field of robotics. This part of the +report focuses on the implementation of the YOLO-v3 (You Only Look Once) model +for computer vision in our robot, covering aspects such as database +management, personal database, annotation, learning, training, implementation, +and deployment. + +\subsection{YOLO-v3 Model} +\subsubsection{Introduction} +% Add content here +YOLO-v3 ( You Only Look Once ) is a state of the art real time objection +algorithm, Created by Joseph Redmon and Al Farhadi, this model is faster and +processes better than other competition. +It excels in single pass detection, real time detection, high accuracy, +versatility and objectness score. This makes it an ideal +solution for the implementation of computer vision in our project + +\subsubsection{Database} +% Add content here +A well made database is essential for the robustness of the implementation of +Computer Vision. There is an inbuilt database present for public usage made by +Microsoft with common objects present in the world. This collection is +perfectly suitable for our project since our project uses a robot that moves in +common spaces and the ability to detect this will be a great fortune for the +entirety of the project. + +\subsubsection{Personal Database} +% Add content here +Due to the lack of time available for the project’s completion. The painstaking +problem of taking individual photos were helped with the help of a python +library called “google-image-download” through which we were able to procure +images for our database as well as personal photos taken. + +\begin{center} + \includegraphics[width=1\linewidth]{personal.png} + \fontsize{10}{12}\selectfont + Fig. 1. Public Database +\end{center} + +\subsubsection{Public Database} +% Add content here +There was also an opportunity to use the public database created by Microsoft +named COCO (Common Objects in Context) with helpful pictures to make the +database more robust + +\begin{center} + \includegraphics[width=1\linewidth]{Screenshot 2024-01-23 at 14.37.52.png} + \fontsize{10}{12}\selectfont + Fig. 2. Public Database +\end{center} + +\subsubsection{Annotation} +% Add content here +To annotate, the label.mg software was used to create classes and then annotate +the images present in the dataset. This software lets us create bounding boxes +for each of the classes and helps us get a more fine-grain dataset with real +usage value. + +\begin{center} + \includegraphics[width=1\linewidth]{Screenshot 2024-01-23 at 14.56.55.png} + \fontsize{10}{12}\selectfont + Fig. 3. Annotation +\end{center} +\subsection{Learning and Training} +\subsubsection{Introduction} +A database alone cannot act in the field of Computer Vision. It needs to be +trained and deployed in a meaningful manner for optimal success. With the help +of some training tools we are able to train a model that is suited for our +needs and will work in a smooth and possible manner. + +\subsubsection{Training} +To train the model, the usage of the ‘darknet model’ (An open source Neural +Network) created by Joseph Redmon was used. To train the model, the coco data +was modified and then the train command from the Neural Network was used to run +until a completed dataset was achieved. + +\begin{center} + \includegraphics[width=1\linewidth]{Screenshot 2024-01-22 at 11.31.55.png} + \fontsize{10}{12}\selectfont + Fig. 4. Training the model +\end{center} + +\subsection{Implementation and Deployment to the Robot} +\subsubsection{Initial Implementation} +For the initial implementation, a code had been devised for running the model +on the computer webcam to test its accuracy and detection in common objects +such as Phone, Person and cutlery. The code included the method on how to run +the configuration and weights via the darknet as well as the creation of +bounding boxes for the recognised objects. +\begin{center} + \includegraphics[width=1\linewidth]{Screenshot 2024-01-23 at 13.54.55.png} + \fontsize{10}{12}\selectfont + Fig. 5. Proof of Concept +\end{center} + +\subsubsection{Implementation and Deployment to the Robot} +To Deploy the role of computer vision to the client application, the creation +of a class was implemented in the entirety of the software code. Once the +location of the names, configuration files and its corresponding weight’s +location were set and the function implemented for live streaming, the +implementation of bounding boxes as well as the method to process the frame was +to be completed.Once done the implementation to the client application was said +to be complete. + +\begin{center} + + \includegraphics[width=1\linewidth]{420838415_367467519380279_4625359774119026473_n.jpg} + \fontsize{10}{12}\selectfont + Fig. 5. Deployment in rpi camera +\end{center} + +\subsection{Drawbacks} +There are no perfections in any project, and the same can also be said to the +Computer Vision part of the project, despite many setbacks the possibility to +learn and fix were never put to rest. + +\subsubsection{Issue 1: Unsatisfactory Dataset} +Due to time constraints and the lack of efficient and satisfactory photos for +training, the overall robustness of the trained model wasn’t up to par. The +model doesn’t resonate a perfect match to all the objects that were shown to it +and takes preference to some rather than the other. + +\subsubsection{Solution} +To solve this problem, the usage of a robust dataset needs to be put to use as +well as running more EPOCHS so that the model can learn more from the data and +result in optimal success. + +\subsubsection{Issue 2: Error in Bounding Boxes} +While trying to implement the code, we could see that the bounding box on the +corresponding objects were moved by a certain value from the center of the +object detected, this was a problem for the future user. + +\subsubsection{Solution} +The normal logic while implementing bounding boxes is to assume that the 0 +point is in the centre of the screen, this in fact was factually incorrect and +the actuality states that the 0 point is in the edge of the screen, which +resulted in the offset when it came to the bounding box, the solution is rather +simple, when it comes to writing the code for the bounding box, writing where +the position of the axes are located helped in fixing the centre coordinates of +the bounding box. + +\begin{center} + \includegraphics[width=1\linewidth]{Screenshot 2024-01-23 at 13.46.13.png} + \fontsize{10}{12}\selectfont + Fig. 6. Solution 2 - Fixing the error in bounding boxes +\end{center} + +\subsubsection{Issue 3: Inverse Output in Recognized Image} +While mounting the camera to the robot, and running the live stream of the +image, we could see that there is an inversion of the resulting output given by +the camera module. This isn’t user-friendly and had to be fixed. + +\subsubsection{Solution} +To combat this situation, the usage of the anti-aliasing command present in the +cv2 library was used, which helped in rotating the inverse image by 180 degrees +and hence giving an output to the user that is legible. + +\begin{center} + \includegraphics[width=1\linewidth]{Screenshot 2024-01-23 at 13.37.03.png} + \fontsize{10}{12}\selectfont + Fig. 7. Solution 3 - Using Anti Aliasing to invert the text +\end{center} + +\subsection{Conclusions} +In conclusion, the implementation of the model for computer vision in our +robot has been a challenging yet rewarding endeavour. The model, with its +real-time object detection capabilities and high accuracy, proved to be an +ideal solution for our project, particularly in the context of a robot +navigating common spaces. +\newline +Despite these challenges, it is important to recognize that perfection is an +elusive goal, especially in complex projects like computer vision for robotics. +Each issue encountered provided an opportunity to learn, adapt, and refine the +system. Moving forward, continuous refinement, the acquisition of a more +diverse dataset, and the application of advanced training techniques will +contribute to further enhancing the model's performance. +\newline +We can also see the results while running EPOCH's there are various parameters +to look after, such as overfitting and underfitting, to elucidate more on this. +Overfitting : If the model starts performing well on the training data but +poorly on new, unseen data (validation or test set), it might be overfitting. +In such instances reducing the number of EPOCHS may help. + +Underfitting : If the model has not yet learnt patterns in it's data, it's +performance may be poor, increasing the number of EPOCH's will be suited. + +Convergence : At times there can be instances where the model converges within +a few EPOCH's this comes to the conclusion that model has been trained with +sufficiency. + +\begin{center} + \includegraphics[width=1\linewidth]{labels_correlogram.jpg} + \fontsize{10}{12}\selectfont + Fig. 8. Histogram with confidence over all axes +\end{center} + +from the above picture we can see that confidence in the trained model within +all axes lead to around lead to an average confidence of 60\% which isn't of +the highest quality but shows reasonable outcomes with the time constraint. + +\begin{center} + \includegraphics[width=1\linewidth]{results.png} + \fontsize{10}{12}\selectfont + Fig. 9. Results of running EPOCHs +\end{center} + +In the above picture we can see the results after running 100 EPOCH's, as one +may notice the epoch's aren't smooth which may result in un-smooth recognition. + +Various reasons may be the cause, from the amount of photos, EPOCH's. Other +reasons may include not using a larger model. + +To Conclude, the overall working of the model has been a moderate success but +it could be better with time and planning in advance. + +\newpage +\section{Summary} + +As a result of the project, a robot was built and programmed. It has the +ability to be +controlled remotely thorught a dedicated app, which also streams the video. +The robot can be controlled + +In conclusion, the successful implementation of remote control and video +streaming aligns with the project’s overarching goals. The robust communication +system and real-time video monitoring capabilities significantly contribute to +the ECLIPSE project, enhancing the remote inspection system’s capabilities in +challenging and inaccessible environments. + +\subsection{Range of application and limitiations} +In general, the robot can be used for +\begin{itemize} + \item exploring confined spaces, + \item traversing rought terrain, + \item grabbing small objects, + \item remote vision based controlling with human operator, + \item autonomus recognition of common objects. +\end{itemize} + +The biggest limitations are: +\begin{itemize} + \item Uncertain remote control range. + \item Limited traction of the wheels. + \item Unreliable gripper action - consequence of cheap servos. + \item Time delay on the camera view due the fact that its encoded on RPi, + send via tcp and decoded on client side (up to 3 seconds). It can even + reach to + 9s if we apply the Computer Vision and the the robot is not withing line + of + sight. + \item Computer vision problem (in our model) due to fact that we didnt put + too much epochs into setting (it should be around 276 insteed of 100), + and + thats the reason for poor confidance level of the model reaching below + 0.5 , + because we didnt achive stable losses. +\end{itemize} + +\subsection{Future work} +\subsubsection{Software} +To enhance the application, consider refining the user interface by +incorporating icons for buttons, exploring cleaner layouts, and potentially +introducing a tabbed interface for additional features. Strengthen error +handling by providing informative error messages and implementing a logging +mechanism for error tracking and analysis. Allow users greater control over +settings by enabling configuration through a settings dialog, saving +preferences between sessions, and utilizing a configuration file. Improve +camera and vision features by supporting multiple video sources and exploring +advanced functionalities such as object tracking. Enhance robot control with +different modes and customizable keyboard shortcuts. Refine servo control UI +with sliders, introduce a calibration feature, and enable saving/loading of +predefined servo angle configurations. Prioritize networking and security by +implementing secure communication protocols, authentication mechanisms, and +network discovery features for streamlined setup. Create thorough +documentation, including tooltips and context-sensitive help, and introduce +multi-language support. Implement unit tests for critical functions, optimize +code for performance, and explore feedback mechanisms for user input and +ongoing improvement. + +\subsubsection{Mechanics} +The core of the mechanical design is very well thought overall, and it +does not need any major improvements. In the future the main chassis +could be expanded a bit to provide more space for fitting the cables, as +mounting everything inside proved to be tricky. Even +though enough space was left for all the electronics, the main PCB grew +substantially during the development which decreased the amount of cable +management space, and increased the overall time needed to assemble the +chassis. Most of the possible, and quite needed improvements would include +redesigning everything around better, more expensive parts. If the actuators +and wheels were in pair with the chassis, overall functionality of the system +would massively improve. +\subsubsection{Low Level Programming} +It could implement algorithm to reduce slippage of middle wheel. + +\subsubsection{Hardware} +In next iteration, the missing capacitors and wrong footprint could be fixed. +Apart from that, easier to use connectors for motors could be used. +\subsubsection{Computer Vision} +It could be improved by using better dataset or training the model with more +EPOCHS. + +\newpage +\begin{thebibliography}{9} + \bibitem{stm32reference} STM32F103 Reference Manual (2020), \emph{ST + Microelectronics} + \bibitem{python} Python Software Foundation. Python Language Reference, + version + 3.7. Available at \url{www.python.org} + \bibitem{pytq} PyQt5. Riverbank Computing. Available at + \url{www.riverbankcomputing.com/software/pyqt/} + \bibitem{libcam} Libcam Project. Available at \url{www.libcamproject.org} + \bibitem{yolo} YOLO Whitepage + \url{www.pjreddie.com/media/files/papers/YOLOv3.pdf} + \bibitem{coco} COCO dataset \url{www.cocodataset.org/#home} + \bibitem{discussion} Discussion on Precision + \url{www.github.com/ultralytics/yolov5/issues/7552} + \bibitem{hat} Official Raspberry Pi HAT guide + \url{www.github.com/raspberrypi/hats} +\end{thebibliography} + +\newpage +\section*{Appendices} +\appendix +\section{Technical drawing of the robot} +For technical drawings, see next pages. +\section{Electrical schematics} +For electrical schematics, see next pages. +\section{Project charter} +The original project charter, exported as pdf, can be found attached. +\section{Project schedule} +The original project shcedule is attached. +The modifications were as follow: +\vspace{15pt} + +\begin{tabular}{|c|c|c|} + \hline + Section & Issues & + Consequence \\ \hline + Mechanics & Late 3D printing & Late + integration and final tests \\ \hline + Software & & + \\ \hline + Low Level Software & & + \\ \hline + Hardware & Missing capacitors, resulting in broken board & Tests + delayed by 3 + weeks + \\ \hline + Computer Vision & Not well requirements for OpenCV interface & Late + integration + \\ \hline +\end{tabular} +\includepdf[scale=1]{pdf/assembly.pdf} +\includepdf[scale=1]{pdf/chasis.pdf} +\includepdf[scale=1,angle=90,pages={1-4}]{pdf/eclipse_schematic.pdf} +\includepdf[scale=1,pages={1-2}]{pdf/charter.pdf} +\includepdf[scale=1,pages={1-3}]{pdf/schedule.pdf} + +\end{document} diff --git a/report/img/420838415_367467519380279_4625359774119026473_n.jpg b/report/img/420838415_367467519380279_4625359774119026473_n.jpg new file mode 100644 index 0000000..ed34ca5 Binary files /dev/null and b/report/img/420838415_367467519380279_4625359774119026473_n.jpg differ diff --git a/report/img/Airpods pro_168 11.45.50.jpg b/report/img/Airpods pro_168 11.45.50.jpg new file mode 100644 index 0000000..81878ad Binary files /dev/null and b/report/img/Airpods pro_168 11.45.50.jpg differ diff --git a/report/img/Airpods pro_168.jpg b/report/img/Airpods pro_168.jpg new file mode 100644 index 0000000..7022e24 Binary files /dev/null and b/report/img/Airpods pro_168.jpg differ diff --git a/report/img/Airpods pro_169 11.45.50.jpg b/report/img/Airpods pro_169 11.45.50.jpg new file mode 100644 index 0000000..3ebfe8f Binary files /dev/null and b/report/img/Airpods pro_169 11.45.50.jpg differ diff --git a/report/img/Screenshot 2024-01-22 at 11.31.55.png b/report/img/Screenshot 2024-01-22 at 11.31.55.png new file mode 100644 index 0000000..8c4176b Binary files /dev/null and b/report/img/Screenshot 2024-01-22 at 11.31.55.png differ diff --git a/report/img/Screenshot 2024-01-22 at 11.35.08.png b/report/img/Screenshot 2024-01-22 at 11.35.08.png new file mode 100644 index 0000000..6e4599f Binary files /dev/null and b/report/img/Screenshot 2024-01-22 at 11.35.08.png differ diff --git a/report/img/Screenshot 2024-01-23 at 13.37.03.png b/report/img/Screenshot 2024-01-23 at 13.37.03.png new file mode 100644 index 0000000..1e50da7 Binary files /dev/null and b/report/img/Screenshot 2024-01-23 at 13.37.03.png differ diff --git a/report/img/Screenshot 2024-01-23 at 13.46.13.png b/report/img/Screenshot 2024-01-23 at 13.46.13.png new file mode 100644 index 0000000..4258fc4 Binary files /dev/null and b/report/img/Screenshot 2024-01-23 at 13.46.13.png differ diff --git a/report/img/Screenshot 2024-01-23 at 13.54.55.png b/report/img/Screenshot 2024-01-23 at 13.54.55.png new file mode 100644 index 0000000..99a6458 Binary files /dev/null and b/report/img/Screenshot 2024-01-23 at 13.54.55.png differ diff --git a/report/img/Screenshot 2024-01-23 at 14.37.52.png b/report/img/Screenshot 2024-01-23 at 14.37.52.png new file mode 100644 index 0000000..5703bfe Binary files /dev/null and b/report/img/Screenshot 2024-01-23 at 14.37.52.png differ diff --git a/report/img/Screenshot 2024-01-23 at 14.55.16.png b/report/img/Screenshot 2024-01-23 at 14.55.16.png new file mode 100644 index 0000000..e33c01b Binary files /dev/null and b/report/img/Screenshot 2024-01-23 at 14.55.16.png differ diff --git a/report/img/Screenshot 2024-01-23 at 14.56.55.png b/report/img/Screenshot 2024-01-23 at 14.56.55.png new file mode 100644 index 0000000..f5e205f Binary files /dev/null and b/report/img/Screenshot 2024-01-23 at 14.56.55.png differ diff --git a/report/img/arm.png b/report/img/arm.png new file mode 100644 index 0000000..3bb33bd Binary files /dev/null and b/report/img/arm.png differ diff --git a/report/img/board1.jpg b/report/img/board1.jpg new file mode 100644 index 0000000..b4a03e3 Binary files /dev/null and b/report/img/board1.jpg differ diff --git a/report/img/board1.png b/report/img/board1.png new file mode 100644 index 0000000..6df6ade Binary files /dev/null and b/report/img/board1.png differ diff --git a/report/img/boardfootprint.jpg b/report/img/boardfootprint.jpg new file mode 100644 index 0000000..d893b0e Binary files /dev/null and b/report/img/boardfootprint.jpg differ diff --git a/report/img/boardfootprint.png b/report/img/boardfootprint.png new file mode 100644 index 0000000..76d2e74 Binary files /dev/null and b/report/img/boardfootprint.png differ diff --git a/report/img/compression.png b/report/img/compression.png new file mode 100644 index 0000000..23874f8 Binary files /dev/null and b/report/img/compression.png differ diff --git a/report/img/cubemx.png b/report/img/cubemx.png new file mode 100644 index 0000000..b94c5a6 Binary files /dev/null and b/report/img/cubemx.png differ diff --git a/report/img/diagram.png b/report/img/diagram.png new file mode 100644 index 0000000..dc54f97 Binary files /dev/null and b/report/img/diagram.png differ diff --git a/report/img/dirtynozzle.jpg b/report/img/dirtynozzle.jpg new file mode 100644 index 0000000..db4d9c6 Binary files /dev/null and b/report/img/dirtynozzle.jpg differ diff --git a/report/img/dirtysetup.jpg b/report/img/dirtysetup.jpg new file mode 100644 index 0000000..1570ff3 Binary files /dev/null and b/report/img/dirtysetup.jpg differ diff --git a/report/img/fusion360.png b/report/img/fusion360.png new file mode 100644 index 0000000..abe4ead Binary files /dev/null and b/report/img/fusion360.png differ diff --git a/report/img/gripper.png b/report/img/gripper.png new file mode 100644 index 0000000..dcd51f8 Binary files /dev/null and b/report/img/gripper.png differ diff --git a/report/img/gui.png b/report/img/gui.png new file mode 100644 index 0000000..3e4b1e6 Binary files /dev/null and b/report/img/gui.png differ diff --git a/report/img/labels_correlogram.jpg b/report/img/labels_correlogram.jpg new file mode 100644 index 0000000..ee4897a Binary files /dev/null and b/report/img/labels_correlogram.jpg differ diff --git a/report/img/part.png b/report/img/part.png new file mode 100644 index 0000000..3bb33bd Binary files /dev/null and b/report/img/part.png differ diff --git a/report/img/pcblayout.png b/report/img/pcblayout.png new file mode 100644 index 0000000..9746c42 Binary files /dev/null and b/report/img/pcblayout.png differ diff --git a/report/img/personal.png b/report/img/personal.png new file mode 100644 index 0000000..b72ef3f Binary files /dev/null and b/report/img/personal.png differ diff --git a/report/img/pwr.png b/report/img/pwr.png new file mode 100644 index 0000000..16676f9 Binary files /dev/null and b/report/img/pwr.png differ diff --git a/report/img/results.png b/report/img/results.png new file mode 100644 index 0000000..e9ec2ba Binary files /dev/null and b/report/img/results.png differ diff --git a/report/img/rpihat1.png b/report/img/rpihat1.png new file mode 100644 index 0000000..4a39f40 Binary files /dev/null and b/report/img/rpihat1.png differ diff --git a/report/img/rpihat1.webp b/report/img/rpihat1.webp new file mode 100644 index 0000000..b79098a Binary files /dev/null and b/report/img/rpihat1.webp differ diff --git a/report/pdf/assembly.pdf b/report/pdf/assembly.pdf new file mode 100644 index 0000000..faf43f0 Binary files /dev/null and b/report/pdf/assembly.pdf differ diff --git a/report/pdf/charter.pdf b/report/pdf/charter.pdf new file mode 100644 index 0000000..a85f694 Binary files /dev/null and b/report/pdf/charter.pdf differ diff --git a/report/pdf/chasis.pdf b/report/pdf/chasis.pdf new file mode 100644 index 0000000..7a87dd0 Binary files /dev/null and b/report/pdf/chasis.pdf differ diff --git a/report/pdf/eclipse_schematic.pdf b/report/pdf/eclipse_schematic.pdf new file mode 100644 index 0000000..14a5026 Binary files /dev/null and b/report/pdf/eclipse_schematic.pdf differ diff --git a/report/pdf/project_charter.pdf b/report/pdf/project_charter.pdf new file mode 100644 index 0000000..e25f21f Binary files /dev/null and b/report/pdf/project_charter.pdf differ diff --git a/report/pdf/schedule.pdf b/report/pdf/schedule.pdf new file mode 100644 index 0000000..b3d3d36 Binary files /dev/null and b/report/pdf/schedule.pdf differ diff --git a/report/project_report.md b/report/project_report.md deleted file mode 100644 index 2717010..0000000 --- a/report/project_report.md +++ /dev/null @@ -1,21 +0,0 @@ -# A fancy titled project - Project report - -## Introduction - -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Eget nunc scelerisque viverra mauris in aliquam sem. Nunc sed id semper risus in hendrerit gravida rutrum. Ultrices eros in cursus turpis massa. At risus viverra adipiscing at in. Posuere urna nec tincidunt praesent semper feugiat nibh. Nascetur ridiculus mus mauris vitae ultricies. Volutpat odio facilisis mauris sit amet massa vitae tortor condimentum. Fermentum odio eu feugiat pretium nibh ipsum consequat nisl. Luctus venenatis lectus magna fringilla. Feugiat in fermentum posuere urna. Nisl rhoncus mattis rhoncus urna neque viverra justo. Ultricies integer quis auctor elit sed vulputate. - -## Review of the previous work - -Arcu non sodales neque sodales. Accumsan in nisl nisi scelerisque eu ultrices vitae auctor. Pellentesque adipiscing commodo elit at imperdiet. Morbi blandit cursus risus at ultrices mi tempus imperdiet nulla. Neque gravida in fermentum et sollicitudin ac orci. Nisl nunc mi ipsum faucibus vitae aliquet nec. Tempor id eu nisl nunc mi ipsum. Tristique senectus et netus et malesuada. In hac habitasse platea dictumst quisque sagittis. Ultricies tristique nulla aliquet enim tortor at auctor. Diam quis enim lobortis scelerisque fermentum dui faucibus in ornare. Sagittis aliquam malesuada bibendum arcu vitae elementum. Dignissim convallis aenean et tortor. Eget mi proin sed libero. Id aliquet risus feugiat in ante metus. - -## Project evaluation - -Vitae turpis massa sed elementum tempus egestas sed. Volutpat commodo sed egestas egestas. Non pulvinar neque laoreet suspendisse. In arcu cursus euismod quis viverra nibh cras. Enim neque volutpat ac tincidunt. Odio facilisis mauris sit amet massa. A erat nam at lectus. Nascetur ridiculus mus mauris vitae ultricies. At in tellus integer feugiat scelerisque. Cursus euismod quis viverra nibh. Curabitur gravida arcu ac tortor dignissim convallis. Dolor morbi non arcu risus. Aliquam etiam erat velit scelerisque. Pellentesque dignissim enim sit amet venenatis urna. Porttitor lacus luctus accumsan tortor posuere ac ut consequat. Eros in cursus turpis massa tincidunt dui ut. Neque viverra justo nec ultrices dui sapien eget mi. - -## Experiments - -Volutpat ac tincidunt vitae semper. Lorem mollis aliquam ut porttitor leo a diam. Euismod lacinia at quis risus sed vulputate odio ut enim. Fringilla ut morbi tincidunt augue interdum velit euismod. Phasellus vestibulum lorem sed risus ultricies tristique nulla aliquet enim. Massa sed elementum tempus egestas sed sed risus. Euismod elementum nisi quis eleifend quam adipiscing vitae proin sagittis. Sem nulla pharetra diam sit. Volutpat maecenas volutpat blandit aliquam etiam. Blandit turpis cursus in hac habitasse platea. Nisi scelerisque eu ultrices vitae auctor eu augue ut. Accumsan sit amet nulla facilisi. - -## Conclusions - -Turpis in eu mi bibendum neque. Neque viverra justo nec ultrices dui sapien. Risus sed vulputate odio ut enim blandit volutpat maecenas volutpat. Laoreet suspendisse interdum consectetur libero id faucibus nisl tincidunt. Sagittis purus sit amet volutpat consequat mauris nunc congue nisi. Mauris pharetra et ultrices neque ornare aenean euismod. Scelerisque mauris pellentesque pulvinar pellentesque. In hac habitasse platea dictumst quisque sagittis. Scelerisque varius morbi enim nunc faucibus a pellentesque sit. Scelerisque viverra mauris in aliquam sem. Tellus molestie nunc non blandit massa. Viverra accumsan in nisl nisi. \ No newline at end of file diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000..aab818d Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/computer-vision/README.md b/src/computer-vision/README.md new file mode 100644 index 0000000..16dc450 --- /dev/null +++ b/src/computer-vision/README.md @@ -0,0 +1,3 @@ +## Computer vision + +This place holds the code that is used for computer vision part of the project. diff --git a/src/computer-vision/coco.names b/src/computer-vision/coco.names new file mode 100644 index 0000000..16315f2 --- /dev/null +++ b/src/computer-vision/coco.names @@ -0,0 +1,80 @@ +person +bicycle +car +motorbike +aeroplane +bus +train +truck +boat +traffic light +fire hydrant +stop sign +parking meter +bench +bird +cat +dog +horse +sheep +cow +elephant +bear +zebra +giraffe +backpack +umbrella +handbag +tie +suitcase +frisbee +skis +snowboard +sports ball +kite +baseball bat +baseball glove +skateboard +surfboard +tennis racket +bottle +wine glass +cup +fork +knife +spoon +bowl +banana +apple +sandwich +orange +broccoli +carrot +hot dog +pizza +donut +cake +chair +sofa +pottedplant +bed +diningtable +toilet +tvmonitor +laptop +mouse +remote +keyboard +cell phone +microwave +oven +toaster +sink +refrigerator +book +clock +vase +scissors +teddy bear +hair drier +toothbrush \ No newline at end of file diff --git a/src/computer-vision/pest.cfg b/src/computer-vision/pest.cfg new file mode 100644 index 0000000..cfca3cf --- /dev/null +++ b/src/computer-vision/pest.cfg @@ -0,0 +1,182 @@ +[net] +# Testing +batch=1 +subdivisions=1 +# Training +# batch=64 +# subdivisions=2 +width=416 +height=416 +channels=3 +momentum=0.9 +decay=0.0005 +angle=0 +saturation = 1.5 +exposure = 1.5 +hue=.1 + +learning_rate=0.001 +burn_in=1000 +max_batches = 500200 +policy=steps +steps=400000,450000 +scales=.1,.1 + +[convolutional] +batch_normalize=1 +filters=16 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=32 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=64 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=1 + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +########### + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=255 +activation=linear + + + +[yolo] +mask = 3,4,5 +anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 +classes=80 +num=6 +jitter=.3 +ignore_thresh = .7 +truth_thresh = 1 +random=1 + +[route] +layers = -4 + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[upsample] +stride=2 + +[route] +layers = -1, 8 + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=255 +activation=linear + +[yolo] +mask = 0,1,2 +anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 +classes=80 +num=6 +jitter=.3 +ignore_thresh = .7 +truth_thresh = 1 +random=1 diff --git a/src/computer-vision/pest.weights b/src/computer-vision/pest.weights new file mode 100644 index 0000000..aad7e6c Binary files /dev/null and b/src/computer-vision/pest.weights differ diff --git a/src/desktop/.gitignore b/src/desktop/.gitignore new file mode 100644 index 0000000..9f11b75 --- /dev/null +++ b/src/desktop/.gitignore @@ -0,0 +1 @@ +.idea/ diff --git a/src/desktop/README.md b/src/desktop/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/desktop/README.md @@ -0,0 +1 @@ + diff --git a/src/desktop/camera_stream.py b/src/desktop/camera_stream.py new file mode 100644 index 0000000..8274807 --- /dev/null +++ b/src/desktop/camera_stream.py @@ -0,0 +1,32 @@ +import cv2 +import numpy as np + +# Create a VideoCapture object +cap = cv2.VideoCapture('tcp://192.168.0.20:8494') + +# Check if camera opened successfully +if not cap.isOpened(): + print("Error opening video stream") + +# Read until video is completed +while cap.isOpened(): + # Capture frame-by-frame + ret, frame = cap.read() + if ret: + + frame = cv2.rotate(frame,cv2.ROTATE_180) + + # Display the resulting frame + cv2.imshow('Frame', frame) + + # Press Q on keyboard to exit + if cv2.waitKey(25) & 0xFF == ord('q'): + break + else: + break + +# Release the video capture and video write objects +cap.release() + +# Closes all the frames +cv2.destroyAllWindows() diff --git a/src/desktop/client.py b/src/desktop/client.py new file mode 100644 index 0000000..83efa8f --- /dev/null +++ b/src/desktop/client.py @@ -0,0 +1,266 @@ +import sys +from PyQt5.QtWidgets import ( + QApplication, QWidget, QVBoxLayout, QLabel, QTextEdit, + QPushButton, QProgressBar, QHBoxLayout, QStatusBar, QInputDialog +) +from PyQt5.QtGui import QImage, QPixmap, QTransform +from PyQt5.QtCore import QTimer, Qt +import cv2 +import numpy as np +import socket +import keyboard +import qdarkstyle +import os + + +class ClientApp(QWidget): + def __init__(self): + super().__init__() + self.log_text_edit = QTextEdit(self) + self.error_logged = False + self.connection_status = QLabel(self) + self.speedometer = QProgressBar(self) + self.init_video_capture() + self.init_network_settings() + self.init_robot_controls() + self.init_servo_controls() + self.init_ui() + + + def init_video_capture(self): + print("Loading YOLO model...") + self.cap = cv2.VideoCapture('tcp://192.168.0.3:8494') + if not self.cap.isOpened(): + self.show_error("Error: Unable to connect to the video stream. Check the connection and try again.") + # self.net = cv2.dnn.readNet('src\computer-vision\pest.weights', 'src\computer-vision\pest.cfg') + #self.classes = [] + #with open('src\computer-vision\coco.names', 'r') as f: + # self.classes = [line.strip() for line in f.readlines()] + # self.layer_names = self.net.getLayerNames() + #layer_indexes = self.net.getUnconnectedOutLayers() + + #self.output_layers = [self.layer_names[i - 1] for i in layer_indexes] + #print("YOLO model loaded successfully.") + def init_network_settings(self): + self.server_ip = '192.168.0.3' + self.server_port = 12345 + + def init_robot_controls(self): + self.key_speeds = {'w': [10, 10], 's': [-10, -10], 'a': [-5, 5], 'd': [5, -5]} + self.speed = [0, 0] + self.default_speed = self.speed.copy() + self.rotate = False + + def init_servo_controls(self): + self.servo_angles = {'servo1': 90, 'servo2': 90, 'servo3': 90, 'servo4' : 90} + self.servo_timers = {'servo1': None, 'servo2': None, 'servo3': None,'servo4': None} + self.servo_labels = {'servo1': None, 'servo2': None, 'servo3': None,'servo4': None} + + def init_ui(self): + self.setWindowTitle('Robot Control App') + self.setGeometry(100, 100, 800, 600) + self.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5()) + + layout = QVBoxLayout(self) + + self.image_label = QLabel(self) + layout.addWidget(self.image_label) + + self.instructions_label = QLabel(""" +

Robot Control:

+ + + + + + +
WIncrease speed
SDecrease speed
ATurn left
DTurn right
+ """, self) + layout.addWidget(self.instructions_label) + + # Speedometer + speed_layout = QHBoxLayout() + speed_layout.addWidget(QLabel("Speed:")) + speed_layout.addWidget(self.speedometer) + layout.addLayout(speed_layout) + + # Status bar + status_bar = QStatusBar(self) + status_bar.addWidget(self.connection_status) + layout.addWidget(status_bar) + + # Servo controls + servo_layout = QHBoxLayout() + for i in range(1, 5): # Update the range to include servo4 + servo_button = QPushButton(f'Servo {i}', self) + servo_button.clicked.connect(lambda _, index=i: self.handle_servo_button_click(index)) + servo_layout.addWidget(servo_button) + + servo_label = QLabel(f'Current Angle: {self.servo_angles[f"servo{i}"]}', self) + servo_layout.addWidget(servo_label) + self.servo_labels[f'servo{i}'] = servo_label + + layout.addLayout(servo_layout) + + self.log_text_edit.setReadOnly(True) + layout.addWidget(self.log_text_edit) + + self.rotate_button = QPushButton('Rotate Frame', self) + self.rotate_button.clicked.connect(self.toggle_rotate) + layout.addWidget(self.rotate_button) + + self.timer = QTimer(self) + self.timer.timeout.connect(self.update_frame) + self.timer.start(1000 / 30) # 30 fps + + # Initialize status + self.update_connection_status() + + def toggle_rotate(self): + self.rotate = not self.rotate + + def update_connection_status(self): + if self.cap.isOpened(): + self.connection_status.setText("Connected") + self.connection_status.setStyleSheet("color: green") + else: + self.connection_status.setText("Disconnected") + self.connection_status.setStyleSheet("color: red") + + def update_speedometer(self): + abs_speed_0 = abs(self.speed[0]) + abs_speed_1 = abs(self.speed[1]) + max_speed = max(abs_speed_0, abs_speed_1) + self.speedometer.setValue(max_speed) + + def update_frame(self): + try: + self.handle_key_presses() + #ret, frame = self.cap.read() + if not ret: + if not self.error_logged: + self.show_error("Error: Unable to read frame from the video stream.") + self.error_logged = True + return + + #height, width, _ = frame.shape + key_pressed = False + #blob = cv2.dnn.blobFromImage(frame, 0.00392, (416, 416), (0, 0, 0), True, crop=False) + #self.net.setInput(blob) + #outs = self.net.forward(self.output_layers) + + # Process the detections + #for out in outs: + #for detection in out: + #scores = detection[5:] + # class_id = np.argmax(scores) + #confidence = scores[class_id] + # if confidence > 0.1: + # Object detected + # center_x = int(detection[0] * width) + # center_y = int(detection[1] * height) + # w = int(detection[2] * width) + # h = int(detection[3] * height) + + # Rectangle coordinates + # x = int(center_x - w / 2) + # y = int(center_y - h / 2) + + # cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) + #new text with inversion + # cv2.putText(img, f'{classNames[classIds[i]].upper()} {int(confs[i] * 100)}%', (x, y - 10), cv2.FONT_HERSHEY_TRIPLEX, 0.6, (255, 0, 255), 2, cv2.LINE_AA, 180) + + + # Display the frame + self.display_frame(frame) + + + except Exception as e: + if not self.error_logged: + self.show_error(f"Error during frame update: {e}") + self.error_logged = True + def handle_key_presses(self): + key_pressed = False + + for key, speed_change in self.key_speeds.items(): + if keyboard.is_pressed(key): + key_pressed = True + self.speed[0] = max(min((self.speed[0] + 0.2 * speed_change[0]), 100), -100) + self.speed[1] = max(min((self.speed[1] + 0.2 * speed_change[1]), 100), -100) + self.send_command(f'CMD,L,{int(self.speed[0])},R,{int(self.speed[1])}') + + # Control servo4 with "Q" and "E" keys + if keyboard.is_pressed('q'): + self.update_servo_angle(4, max(self.servo_angles['servo4'] - 1, 0), -1) + elif keyboard.is_pressed('e'): + self.update_servo_angle(4, min(self.servo_angles['servo4'] + 1, 180), 1) + + if not key_pressed: + self.speed = self.default_speed.copy() + + self.update_speedometer() + + def send_command(self, command): + try: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.connect((self.server_ip, self.server_port)) + s.sendall(command.encode()) + self.log_text_edit.append(f'Sent command: {command}') + + except Exception as e: + if not self.error_logged: + error_message = f'Error connecting to the server: {e}' + self.log_text_edit.append(error_message) + print(error_message) + self.error_logged = True + + def display_frame(self, frame): + + rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + + if self.rotate: + rgb_image = cv2.rotate(rgb_image, cv2.ROTATE_180) + + h, w, ch = rgb_image.shape + bytes_per_line = ch * w + convert_to_Qt_format = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888) + p = convert_to_Qt_format.scaled(800, 600, Qt.KeepAspectRatio) + self.image_label.setPixmap(QPixmap.fromImage(p)) + + def handle_servo_button_click(self, servo_index): + new_angle, ok = QInputDialog.getInt(self, f'Set Angle for Servo {servo_index}', f'Enter angle (0-180) for Servo {servo_index}:', self.servo_angles[f'servo{servo_index}'], 0, 180) + if ok: + target_angle = new_angle + current_angle = self.servo_angles[f'servo{servo_index}'] + + step = 1 if target_angle > current_angle else -1 + + if self.servo_timers[f'servo{servo_index}']: + self.servo_timers[f'servo{servo_index}'].stop() + + timer = QTimer(self) + timer.timeout.connect(lambda: self.update_servo_angle(servo_index, target_angle, step)) + timer.start(30) + self.servo_timers[f'servo{servo_index}'] = timer + + def update_servo_angle(self, servo_index, target_angle, step): + current_angle = self.servo_angles[f'servo{servo_index}'] + if current_angle != target_angle: + new_angle = current_angle + step + self.servo_angles[f'servo{servo_index}'] = new_angle + self.send_command(f'CMD,S,{int(servo_index)},{int(new_angle)}') + self.servo_labels[f'servo{servo_index}'].setText(f'Current Angle: {new_angle}') + else: + self.servo_timers[f'servo{servo_index}'].stop() + + def show_error(self, message): + error_message = f"{message}" + self.log_text_edit.append(error_message) + print(error_message) + +if __name__ == '__main__': + app = QApplication(sys.argv) + app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5()) + ex = ClientApp() + ex.show() + sys.exit(app.exec_()) diff --git a/src/hardware/README.md b/src/hardware/README.md new file mode 100644 index 0000000..175eea0 --- /dev/null +++ b/src/hardware/README.md @@ -0,0 +1,3 @@ +## Hardware + +This place holds materials and documentation from hardware team. diff --git a/src/instruction.txt b/src/instruction.txt new file mode 100644 index 0000000..a0994f4 --- /dev/null +++ b/src/instruction.txt @@ -0,0 +1,51 @@ + + +1. Setting up the environment: +Ensure that Python is installed on your system. You can download it from the official website: https://www.python.org/downloads/ +Install the necessary Python libraries by running the following command in your terminal: + +pip install PyQt5 opencv-python pyserial keyboard qdarkstyle + +2. Running the Client Application: + +Open the terminal and navigate to the directory where the client application code is located. +Run the client application by executing the following command: + +python client_app.py + +The client application should now be running, and you should see the user interface. + +3. Running the Server on Raspberry Pi: +Ensure that the Raspberry Pi is set up and connected to the same network as your computer. +Transfer the server code to the Raspberry Pi. You can use scp or any other method you prefer. +On the Raspberry Pi, navigate to the directory where the server code is located. +Run the server by executing the following command: + +python server.py + +The server should now be running and waiting for connections from the client. +4. Running the Bash Script: + +On the Raspberry Pi, navigate to the directory where the stream.sh bash script is located. +Make the script executable by running the following command: + +chmod +x stream.sh + +Run the bash script by executing the following command: + +./stream.sh + +The bash script should now be running, capturing and streaming video from the device’s camera. +5. Setting up rc.local: +On the Raspberry Pi, open the rc.local file located in the /etc directory. +Add the following lines to the file before exit 0: + +/home/admin/stream.sh & +python3 /home/admin/server.py & + +Save and close the file. The changes will take effect after a reboot. +6. Controlling the Inspection Device: + +With both the client and server running, you can now control the inspection device. +Use the ‘W’, ‘A’, ‘S’, ‘D’ keys to control the device. ‘W’ and ‘S’ are used to increase and decrease the speed, while ‘A’ and ‘D’ are used to turn left and right, respectively. +The video feed from the inspection device should be displayed in the client application’s user interface. diff --git a/src/raport-dratft.docx b/src/raport-dratft.docx new file mode 100644 index 0000000..b477b3d Binary files /dev/null and b/src/raport-dratft.docx differ diff --git a/src/rpi/README.md b/src/rpi/README.md new file mode 100644 index 0000000..d9badb2 --- /dev/null +++ b/src/rpi/README.md @@ -0,0 +1,3 @@ +## Raspberry Pi + +This place holds the code that is used for Raspberry Pi. diff --git a/src/rpi/rc.local b/src/rpi/rc.local new file mode 100644 index 0000000..a2efee2 --- /dev/null +++ b/src/rpi/rc.local @@ -0,0 +1,19 @@ +# This script is executed at the end of each multiuser runlevel. +# Make sure that the script will "exit 0" on success or any other +# value on error. +# +# In order to enable or disable this script just change the execution +# bits. +# +# By default this script does nothing. + +# Print the IP address +sudo modprobe bcm2835-v4l2 +_IP=$(hostname -I) || true +if [ "$_IP" ]; then + printf "My IP address is %s\n" "$_IP" +fi + +/home/admin/stream.sh & +python3 /home/admin/server.py & +exit 0 diff --git a/src/rpi/server.py b/src/rpi/server.py new file mode 100644 index 0000000..236be6f --- /dev/null +++ b/src/rpi/server.py @@ -0,0 +1,32 @@ +import socket +import serial + +ser = serial.Serial('/dev/ttyS0', 9600) + +def start_server(): + host = '0.0.0.0' # Listen on all interfaces + port = 12345 # Use a non-privileged port number + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.bind((host, port)) + s.listen() + print(f'Server is listening on {host}:{port}') + while True: + conn, addr = s.accept() + print('app connect') + with conn: + print('Connected by', addr) + while True: + try: + data = conn.recv(1024) + if not data: + break + print('Received', repr(data)) + ser.write(data) + except ConnectionResetError: + print("app disconnect") + return + +if __name__ == '__main__': + start_server() + diff --git a/src/rpi/stream.sh b/src/rpi/stream.sh new file mode 100644 index 0000000..2d3f7eb --- /dev/null +++ b/src/rpi/stream.sh @@ -0,0 +1,5 @@ +#!/bin/bash +while true +do + libcamera-vid -t 0 --inline --listen --width 1920 --height 1080 --framerate 30 --rotation 180 --codec h264 -n -o tcp://0.0.0.0:8494 +done diff --git a/src/stm32/.cproject b/src/stm32/.cproject new file mode 100644 index 0000000..d828193 --- /dev/null +++ b/src/stm32/.cproject @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/stm32/.gitignore b/src/stm32/.gitignore new file mode 100644 index 0000000..b2a295b --- /dev/null +++ b/src/stm32/.gitignore @@ -0,0 +1,4 @@ +Debug/ +Drivers/ +.settings/ +testroot/build/ \ No newline at end of file diff --git a/src/stm32/.mxproject b/src/stm32/.mxproject new file mode 100644 index 0000000..55e6402 --- /dev/null +++ b/src/stm32/.mxproject @@ -0,0 +1,25 @@ +[PreviousLibFiles] +LibFiles=Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_adc.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_adc.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_adc_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_def.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_bus.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_rcc.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_system.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_utils.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_gpio.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_gpio_ex.h;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_gpio.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_dma_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_dma.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_dma.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_cortex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_cortex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_pwr.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_pwr.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_flash.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_flash_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_exti.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_exti.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_tim.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_tim_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_tim.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_uart.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_usart.h;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_adc.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_adc.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_adc_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_def.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_bus.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_rcc.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_system.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_utils.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_gpio.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_gpio_ex.h;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_gpio.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_dma_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_dma.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_dma.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_cortex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_cortex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_pwr.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_pwr.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_flash.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_flash_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_exti.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_exti.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_tim.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_tim_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_tim.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_uart.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_usart.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103x6.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/system_stm32f1xx.h;Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/system_stm32f1xx.c;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/core_sc300.h;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/cmsis_version.h;Drivers/CMSIS/Include/core_armv8mbl.h;Drivers/CMSIS/Include/cmsis_armclang.h;Drivers/CMSIS/Include/core_cm23.h;Drivers/CMSIS/Include/core_cm33.h;Drivers/CMSIS/Include/core_armv8mml.h;Drivers/CMSIS/Include/mpu_armv7.h;Drivers/CMSIS/Include/tz_context.h;Drivers/CMSIS/Include/cmsis_iccarm.h;Drivers/CMSIS/Include/core_cm3.h;Drivers/CMSIS/Include/cmsis_compiler.h;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/mpu_armv8.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/core_sc000.h;Drivers/CMSIS/Include/core_cm1.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/core_cm0.h; + +[PreviousUsedCubeIDEFiles] +SourceFiles=Core/Src/main.c;Core/Src/stm32f1xx_it.c;Core/Src/stm32f1xx_hal_msp.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c;Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/system_stm32f1xx.c;Core/Src/system_stm32f1xx.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c;Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/system_stm32f1xx.c;Core/Src/system_stm32f1xx.c;;; +HeaderPath=Drivers/STM32F1xx_HAL_Driver/Inc;Drivers/STM32F1xx_HAL_Driver/Inc/Legacy;Drivers/CMSIS/Device/ST/STM32F1xx/Include;Drivers/CMSIS/Include;Core/Inc; +CDefines=USE_HAL_DRIVER;STM32F103x6;USE_HAL_DRIVER;USE_HAL_DRIVER; + +[PreviousGenFiles] +AdvancedFolderStructure=true +HeaderFileListSize=3 +HeaderFiles#0=../Core/Inc/stm32f1xx_it.h +HeaderFiles#1=../Core/Inc/stm32f1xx_hal_conf.h +HeaderFiles#2=../Core/Inc/main.h +HeaderFolderListSize=1 +HeaderPath#0=../Core/Inc +HeaderFiles=; +SourceFileListSize=3 +SourceFiles#0=../Core/Src/stm32f1xx_it.c +SourceFiles#1=../Core/Src/stm32f1xx_hal_msp.c +SourceFiles#2=../Core/Src/main.c +SourceFolderListSize=1 +SourcePath#0=../Core/Src +SourceFiles=; + diff --git a/src/stm32/.project b/src/stm32/.project new file mode 100644 index 0000000..85dd8f0 --- /dev/null +++ b/src/stm32/.project @@ -0,0 +1,33 @@ + + + f103-robotics + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + com.st.stm32cube.ide.mcu.MCUProjectNature + com.st.stm32cube.ide.mcu.MCUCubeProjectNature + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + com.st.stm32cube.ide.mcu.MCUCubeIdeServicesRevAev2ProjectNature + com.st.stm32cube.ide.mcu.MCUAdvancedStructureProjectNature + com.st.stm32cube.ide.mcu.MCUSingleCpuProjectNature + com.st.stm32cube.ide.mcu.MCURootProjectNature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/src/stm32/Core/Inc/main.h b/src/stm32/Core/Inc/main.h new file mode 100644 index 0000000..b910d96 --- /dev/null +++ b/src/stm32/Core/Inc/main.h @@ -0,0 +1,109 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.h + * @brief : Header for main.c file. + * This file contains the common defines of the application. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MAIN_H +#define __MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f1xx_hal.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#ifdef __cplusplus +#define CONSTEXPR constexpr +#else +#define CONSTEXPR +#endif + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ +//CONSTEXPR const size_t rx_buf_size = 256; +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); + +/* Exported functions prototypes ---------------------------------------------*/ +void Error_Handler(void); + +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +/* Private defines -----------------------------------------------------------*/ + +#define SERVO3_Pin GPIO_PIN_10 +#define SERVO3_GPIO_Port GPIOB +#define SERVO4_Pin GPIO_PIN_11 +#define SERVO4_GPIO_Port GPIOB +#define M2_IN1_Pin GPIO_PIN_12 +#define M2_IN1_GPIO_Port GPIOB +#define M2_IN2_Pin GPIO_PIN_13 +#define M2_IN2_GPIO_Port GPIOB +#define M1_IN2_Pin GPIO_PIN_14 +#define M1_IN2_GPIO_Port GPIOB +#define M1_IN1_Pin GPIO_PIN_15 +#define M1_IN1_GPIO_Port GPIOB +#define M2_PWM1_Pin GPIO_PIN_8 +#define M2_PWM1_GPIO_Port GPIOA +#define M2_PWM2_Pin GPIO_PIN_9 +#define M2_PWM2_GPIO_Port GPIOA +#define M1_PWM1_Pin GPIO_PIN_10 +#define M1_PWM1_GPIO_Port GPIOA +#define M1_PWM2_Pin GPIO_PIN_11 +#define M1_PWM2_GPIO_Port GPIOA +#define STBY_Pin GPIO_PIN_12 +#define STBY_GPIO_Port GPIOA +#define SERVO1_Pin GPIO_PIN_15 +#define SERVO1_GPIO_Port GPIOA +#define SERVO2_Pin GPIO_PIN_3 +#define SERVO2_GPIO_Port GPIOB +#define DBG_BTN_Pin GPIO_PIN_8 +#define DBG_BTN_GPIO_Port GPIOB +#define DBG_LED_Pin GPIO_PIN_9 +#define DBG_LED_GPIO_Port GPIOB + +/* USER CODE BEGIN Private defines */ +#define STBY_ON() HAL_GPIO_WritePin(STBY_GPIO_Port, STBY_Pin, GPIO_PIN_RESET); +#define STBY_OFF() HAL_GPIO_WritePin(STBY_GPIO_Port, STBY_Pin, GPIO_PIN_SET); + +/* USER CODE END Private defines */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H */ diff --git a/src/stm32/Core/Inc/stm32f1xx_hal_conf.h b/src/stm32/Core/Inc/stm32f1xx_hal_conf.h new file mode 100644 index 0000000..3f78a90 --- /dev/null +++ b/src/stm32/Core/Inc/stm32f1xx_hal_conf.h @@ -0,0 +1,391 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f1xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F1xx_HAL_CONF_H +#define __STM32F1xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ + +#define HAL_MODULE_ENABLED + #define HAL_ADC_MODULE_ENABLED +/*#define HAL_CRYP_MODULE_ENABLED */ +/*#define HAL_CAN_MODULE_ENABLED */ +/*#define HAL_CAN_LEGACY_MODULE_ENABLED */ +/*#define HAL_CEC_MODULE_ENABLED */ +/*#define HAL_CORTEX_MODULE_ENABLED */ +/*#define HAL_CRC_MODULE_ENABLED */ +/*#define HAL_DAC_MODULE_ENABLED */ +#define HAL_DMA_MODULE_ENABLED +/*#define HAL_ETH_MODULE_ENABLED */ +/*#define HAL_FLASH_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +/*#define HAL_I2C_MODULE_ENABLED */ +/*#define HAL_I2S_MODULE_ENABLED */ +/*#define HAL_IRDA_MODULE_ENABLED */ +/*#define HAL_IWDG_MODULE_ENABLED */ +/*#define HAL_NOR_MODULE_ENABLED */ +/*#define HAL_NAND_MODULE_ENABLED */ +/*#define HAL_PCCARD_MODULE_ENABLED */ +/*#define HAL_PCD_MODULE_ENABLED */ +/*#define HAL_HCD_MODULE_ENABLED */ +/*#define HAL_PWR_MODULE_ENABLED */ +/*#define HAL_RCC_MODULE_ENABLED */ +/*#define HAL_RTC_MODULE_ENABLED */ +/*#define HAL_SD_MODULE_ENABLED */ +/*#define HAL_MMC_MODULE_ENABLED */ +/*#define HAL_SDRAM_MODULE_ENABLED */ +/*#define HAL_SMARTCARD_MODULE_ENABLED */ +/*#define HAL_SPI_MODULE_ENABLED */ +/*#define HAL_SRAM_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +/*#define HAL_USART_MODULE_ENABLED */ +/*#define HAL_WWDG_MODULE_ENABLED */ + +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE 8000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE 40000U /*!< LSI Typical Value in Hz */ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature. */ + +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE 32768U /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY 15U /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U + +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_PCCARD_REGISTER_CALLBACKS 0U /* PCCARD register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB 8U /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB 4U /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848_PHY_ADDRESS Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY 0x000000FFU +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY 0x00000FFFU + +#define PHY_READ_TO 0x0000FFFFU +#define PHY_WRITE_TO 0x0000FFFFU + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ +#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver +* Activated: CRC code is present inside driver +* Deactivated: CRC code cleaned from driver +*/ + +#define USE_SPI_CRC 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32f1xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32f1xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32f1xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32f1xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED +#include "stm32f1xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED +#include "stm32f1xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CAN_LEGACY_MODULE_ENABLED + #include "Legacy/stm32f1xx_hal_can_legacy.h" +#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED +#include "stm32f1xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32f1xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32f1xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32f1xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32f1xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32f1xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED +#include "stm32f1xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED +#include "stm32f1xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32f1xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED +#include "stm32f1xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32f1xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32f1xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32f1xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED +#include "stm32f1xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED +#include "stm32f1xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED +#include "stm32f1xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32f1xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32f1xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32f1xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32f1xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32f1xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32f1xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32f1xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32f1xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED +#include "stm32f1xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED +#include "stm32f1xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ +void assert_failed(uint8_t* file, uint32_t line); +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F1xx_HAL_CONF_H */ + diff --git a/src/stm32/Core/Inc/stm32f1xx_it.h b/src/stm32/Core/Inc/stm32f1xx_it.h new file mode 100644 index 0000000..d3376fc --- /dev/null +++ b/src/stm32/Core/Inc/stm32f1xx_it.h @@ -0,0 +1,68 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f1xx_it.h + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F1xx_IT_H +#define __STM32F1xx_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); +void DMA1_Channel6_IRQHandler(void); +void USART2_IRQHandler(void); +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F1xx_IT_H */ diff --git a/src/stm32/Core/Inc/user_logic.h b/src/stm32/Core/Inc/user_logic.h new file mode 100644 index 0000000..22cbfe8 --- /dev/null +++ b/src/stm32/Core/Inc/user_logic.h @@ -0,0 +1,12 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void process(); +void stop_motors(); + +#ifdef __cplusplus +} +#endif diff --git a/src/stm32/Core/Src/main.c b/src/stm32/Core/Src/main.c new file mode 100644 index 0000000..6019713 --- /dev/null +++ b/src/stm32/Core/Src/main.c @@ -0,0 +1,631 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "user_logic.h" +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +ADC_HandleTypeDef hadc1; + +TIM_HandleTypeDef htim1; +TIM_HandleTypeDef htim2; +TIM_HandleTypeDef htim3; + +UART_HandleTypeDef huart2; +DMA_HandleTypeDef hdma_usart2_rx; + +/* USER CODE BEGIN PV */ +uint32_t time_from_last_command = 0; +const uint32_t uart_timeout = 500; +uint8_t emergency_stop = 1; + +uint8_t cmdReceivedFlag = 0; +char usart2_buffer[256]; +void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { + // Check if UART2 trigger the Callback + if (huart->Instance == USART2) { + cmdReceivedFlag = 1; + if (Size < 256) + usart2_buffer[Size] = 0; + time_from_last_command = 0; + + // Start to listening again - IMPORTANT! + HAL_UARTEx_ReceiveToIdle_DMA(&huart2, (uint8_t*) usart2_buffer, 256); + } +} + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +static void MX_GPIO_Init(void); +static void MX_DMA_Init(void); +static void MX_USART2_UART_Init(void); +static void MX_TIM2_Init(void); +static void MX_TIM3_Init(void); +static void MX_TIM1_Init(void); +static void MX_ADC1_Init(void); +static void MX_NVIC_Init(void); +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +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_DMA_Init(); + MX_USART2_UART_Init(); + MX_TIM2_Init(); + MX_TIM3_Init(); + MX_TIM1_Init(); + MX_ADC1_Init(); + + /* Initialize interrupts */ + MX_NVIC_Init(); + /* USER CODE BEGIN 2 */ + HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); + HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2); + HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3); + HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4); +// HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); +// HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2); +// HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3); +// HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4); +// HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); +// HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2); +// HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3); +// HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4); + TIM1->CCR1 = 0; + TIM1->CCR2 = 0; + TIM1->CCR3 = 0; + TIM1->CCR4 = 0; + TIM2->CCR1 = 0; + TIM2->CCR2 = 0; + TIM2->CCR3 = 0; + TIM2->CCR4 = 0; + TIM3->CCR1 = 0; + TIM3->CCR2 = 0; + TIM3->CCR3 = 0; + TIM3->CCR4 = 0; +// HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); +// HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2); +// TIM1->CCMR1 |= 7 << TIM_CCMR1_OC1M_Pos; +// TIM1->CCMR1 |= 7 << TIM_CCMR1_OC2M_Pos; +// TIM1->CCER = TIM_CCER_CC2NE | TIM_CCER_CC1NE; + // TIM1->CCER |= TIM_CCER_CC1NE_Msk | TIM_CCER_CC2NE_Msk; + // TIM1->CCR1 = 0; + // TIM1->CCR2 = 0; + stop_motors(); + HAL_UARTEx_ReceiveToIdle_DMA(&huart2, (uint8_t*) usart2_buffer, 256); + + /* USER CODE END 2 */ + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) { + if (cmdReceivedFlag) { + HAL_GPIO_TogglePin(DBG_LED_GPIO_Port, DBG_LED_Pin); + cmdReceivedFlag = 0; + process(); + } + if (emergency_stop) { + emergency_stop = 0; + stop_motors(); + } + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + } + /* USER CODE END 3 */ +} + +/** + * @brief System Clock Configuration + * @retval None + */ +void SystemClock_Config(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; + RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + Error_Handler(); + } + + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) + { + Error_Handler(); + } + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; + PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV2; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) + { + Error_Handler(); + } +} + +/** + * @brief NVIC Configuration. + * @retval None + */ +static void MX_NVIC_Init(void) +{ + /* DMA1_Channel6_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn); + /* USART2_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(USART2_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(USART2_IRQn); +} + +/** + * @brief ADC1 Initialization Function + * @param None + * @retval None + */ +static void MX_ADC1_Init(void) +{ + + /* USER CODE BEGIN ADC1_Init 0 */ + + /* USER CODE END ADC1_Init 0 */ + + ADC_ChannelConfTypeDef sConfig = {0}; + + /* USER CODE BEGIN ADC1_Init 1 */ + + /* USER CODE END ADC1_Init 1 */ + + /** Common config + */ + hadc1.Instance = ADC1; + hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; + hadc1.Init.ContinuousConvMode = DISABLE; + hadc1.Init.DiscontinuousConvMode = DISABLE; + hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; + hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc1.Init.NbrOfConversion = 1; + if (HAL_ADC_Init(&hadc1) != HAL_OK) + { + Error_Handler(); + } + + /** Configure Regular Channel + */ + sConfig.Channel = ADC_CHANNEL_1; + sConfig.Rank = ADC_REGULAR_RANK_1; + sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; + if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN ADC1_Init 2 */ + + /* USER CODE END ADC1_Init 2 */ + +} + +/** + * @brief TIM1 Initialization Function + * @param None + * @retval None + */ +static void MX_TIM1_Init(void) +{ + + /* USER CODE BEGIN TIM1_Init 0 */ + + /* USER CODE END TIM1_Init 0 */ + + TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_OC_InitTypeDef sConfigOC = {0}; + TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; + + /* USER CODE BEGIN TIM1_Init 1 */ + + /* USER CODE END TIM1_Init 1 */ + htim1.Instance = TIM1; + htim1.Init.Prescaler = 48-1; + htim1.Init.CounterMode = TIM_COUNTERMODE_UP; + htim1.Init.Period = 100; + htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim1.Init.RepetitionCounter = 0; + htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; + if (HAL_TIM_Base_Init(&htim1) != HAL_OK) + { + Error_Handler(); + } + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_PWM_Init(&htim1) != HAL_OK) + { + Error_Handler(); + } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) + { + Error_Handler(); + } + sConfigOC.OCMode = TIM_OCMODE_PWM1; + sConfigOC.Pulse = 0; + sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; + sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; + sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; + sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; + if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK) + { + Error_Handler(); + } + sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; + sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; + sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; + sBreakDeadTimeConfig.DeadTime = 0; + sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; + sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; + sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; + if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN TIM1_Init 2 */ + + /* USER CODE END TIM1_Init 2 */ + HAL_TIM_MspPostInit(&htim1); + +} + +/** + * @brief TIM2 Initialization Function + * @param None + * @retval None + */ +static void MX_TIM2_Init(void) +{ + + /* USER CODE BEGIN TIM2_Init 0 */ + + /* USER CODE END TIM2_Init 0 */ + + + TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_OC_InitTypeDef sConfigOC = {0}; + + /* USER CODE BEGIN TIM2_Init 1 */ + + /* USER CODE END TIM2_Init 1 */ + htim2.Instance = TIM2; + htim2.Init.Prescaler = 532; + htim2.Init.CounterMode = TIM_COUNTERMODE_UP; + htim2.Init.Period = 1800-1; + htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; + if (HAL_TIM_Base_Init(&htim2) != HAL_OK) + { + Error_Handler(); + } + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) + { + Error_Handler(); + } + + if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) + { + Error_Handler(); + } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) + { + Error_Handler(); + } + sConfigOC.OCMode = TIM_OCMODE_PWM1; + sConfigOC.Pulse = 0; + sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; + + if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) + { + Error_Handler(); + } + + if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK) + { + Error_Handler(); + } + + /* USER CODE BEGIN TIM2_Init 2 */ + + /* USER CODE END TIM2_Init 2 */ + HAL_TIM_MspPostInit(&htim2); + +} + +/** + * @brief TIM3 Initialization Function + * @param None + * @retval None + */ +static void MX_TIM3_Init(void) +{ + + /* USER CODE BEGIN TIM3_Init 0 */ + + /* USER CODE END TIM3_Init 0 */ + + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_OC_InitTypeDef sConfigOC = {0}; + + /* USER CODE BEGIN TIM3_Init 1 */ + + /* USER CODE END TIM3_Init 1 */ + htim3.Instance = TIM3; + htim3.Init.Prescaler = 48-1; + htim3.Init.CounterMode = TIM_COUNTERMODE_UP; + htim3.Init.Period = 100; + htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; + if (HAL_TIM_PWM_Init(&htim3) != HAL_OK) + { + Error_Handler(); + } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK) + { + Error_Handler(); + } + sConfigOC.OCMode = TIM_OCMODE_PWM1; + sConfigOC.Pulse = 0; + sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; + if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN TIM3_Init 2 */ + + /* USER CODE END TIM3_Init 2 */ + HAL_TIM_MspPostInit(&htim3); + +} + +/** + * @brief USART2 Initialization Function + * @param None + * @retval None + */ +static void MX_USART2_UART_Init(void) +{ + + /* USER CODE BEGIN USART2_Init 0 */ + + /* USER CODE END USART2_Init 0 */ + + /* USER CODE BEGIN USART2_Init 1 */ + + /* USER CODE END USART2_Init 1 */ + huart2.Instance = USART2; + huart2.Init.BaudRate = 115200; + huart2.Init.WordLength = UART_WORDLENGTH_8B; + huart2.Init.StopBits = UART_STOPBITS_1; + huart2.Init.Parity = UART_PARITY_NONE; + huart2.Init.Mode = UART_MODE_TX_RX; + huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart2.Init.OverSampling = UART_OVERSAMPLING_16; + if (HAL_UART_Init(&huart2) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN USART2_Init 2 */ + + /* USER CODE END USART2_Init 2 */ + +} + +/** + * Enable DMA controller clock + */ +static void MX_DMA_Init(void) +{ + + /* DMA controller clock enable */ + __HAL_RCC_DMA1_CLK_ENABLE(); + +} + +/** + * @brief GPIO Initialization Function + * @param None + * @retval None + */ +static void MX_GPIO_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; +/* USER CODE BEGIN MX_GPIO_Init_1 */ +/* USER CODE END MX_GPIO_Init_1 */ + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOB, M2_IN1_Pin|M2_IN2_Pin|M1_IN2_Pin|M1_IN1_Pin + |DBG_LED_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(STBY_GPIO_Port, STBY_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pins : M2_IN1_Pin M2_IN2_Pin M1_IN2_Pin M1_IN1_Pin + DBG_LED_Pin */ + GPIO_InitStruct.Pin = M2_IN1_Pin|M2_IN2_Pin|M1_IN2_Pin|M1_IN1_Pin + |DBG_LED_Pin; + 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 : STBY_Pin */ + GPIO_InitStruct.Pin = STBY_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(STBY_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pin : DBG_BTN_Pin */ + GPIO_InitStruct.Pin = DBG_BTN_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(DBG_BTN_GPIO_Port, &GPIO_InitStruct); + +/* USER CODE BEGIN MX_GPIO_Init_2 */ +/* USER CODE END MX_GPIO_Init_2 */ +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return state */ + __disable_irq(); + 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, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/src/stm32/Core/Src/stm32f1xx_hal_msp.c b/src/stm32/Core/Src/stm32f1xx_hal_msp.c new file mode 100644 index 0000000..45ab7aa --- /dev/null +++ b/src/stm32/Core/Src/stm32f1xx_hal_msp.c @@ -0,0 +1,427 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f1xx_hal_msp.c + * @brief This file provides code for the MSP Initialization + * and de-Initialization codes. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ +extern DMA_HandleTypeDef hdma_usart2_rx; + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN TD */ + +/* USER CODE END TD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN Define */ + +/* USER CODE END Define */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN Macro */ + +/* USER CODE END Macro */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* External functions --------------------------------------------------------*/ +/* USER CODE BEGIN ExternalFunctions */ + +/* USER CODE END ExternalFunctions */ + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); + /** + * Initializes the Global MSP. + */ +void HAL_MspInit(void) +{ + /* USER CODE BEGIN MspInit 0 */ + + /* USER CODE END MspInit 0 */ + + __HAL_RCC_AFIO_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + /* System interrupt init*/ + + /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled + */ + __HAL_AFIO_REMAP_SWJ_NOJTAG(); + + /* USER CODE BEGIN MspInit 1 */ + + /* USER CODE END MspInit 1 */ +} + +/** +* @brief ADC MSP Initialization +* This function configures the hardware resources used in this example +* @param hadc: ADC handle pointer +* @retval None +*/ +void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(hadc->Instance==ADC1) + { + /* USER CODE BEGIN ADC1_MspInit 0 */ + + /* USER CODE END ADC1_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_ADC1_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**ADC1 GPIO Configuration + PA0-WKUP ------> ADC1_IN0 + PA1 ------> ADC1_IN1 + */ + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USER CODE BEGIN ADC1_MspInit 1 */ + + /* USER CODE END ADC1_MspInit 1 */ + } + +} + +/** +* @brief ADC MSP De-Initialization +* This function freeze the hardware resources used in this example +* @param hadc: ADC handle pointer +* @retval None +*/ +void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) +{ + if(hadc->Instance==ADC1) + { + /* USER CODE BEGIN ADC1_MspDeInit 0 */ + + /* USER CODE END ADC1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_ADC1_CLK_DISABLE(); + + /**ADC1 GPIO Configuration + PA0-WKUP ------> ADC1_IN0 + PA1 ------> ADC1_IN1 + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1); + + /* USER CODE BEGIN ADC1_MspDeInit 1 */ + + /* USER CODE END ADC1_MspDeInit 1 */ + } + +} + +/** +* @brief TIM_Base MSP Initialization +* This function configures the hardware resources used in this example +* @param htim_base: TIM_Base handle pointer +* @retval None +*/ +void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) +{ + if(htim_base->Instance==TIM1) + { + /* USER CODE BEGIN TIM1_MspInit 0 */ + + /* USER CODE END TIM1_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_TIM1_CLK_ENABLE(); + /* USER CODE BEGIN TIM1_MspInit 1 */ + + /* USER CODE END TIM1_MspInit 1 */ + } + else if(htim_base->Instance==TIM2) + { + /* USER CODE BEGIN TIM2_MspInit 0 */ + + /* USER CODE END TIM2_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_TIM2_CLK_ENABLE(); + /* USER CODE BEGIN TIM2_MspInit 1 */ + + /* USER CODE END TIM2_MspInit 1 */ + } + +} + +/** +* @brief TIM_PWM MSP Initialization +* This function configures the hardware resources used in this example +* @param htim_pwm: TIM_PWM handle pointer +* @retval None +*/ +void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm) +{ + if(htim_pwm->Instance==TIM3) + { + /* USER CODE BEGIN TIM3_MspInit 0 */ + + /* USER CODE END TIM3_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_TIM3_CLK_ENABLE(); + /* USER CODE BEGIN TIM3_MspInit 1 */ + + /* USER CODE END TIM3_MspInit 1 */ + } + +} + +void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(htim->Instance==TIM1) + { + /* USER CODE BEGIN TIM1_MspPostInit 0 */ + + /* USER CODE END TIM1_MspPostInit 0 */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**TIM1 GPIO Configuration + PA8 ------> TIM1_CH1 + PA9 ------> TIM1_CH2 + PA10 ------> TIM1_CH3 + PA11 ------> TIM1_CH4 + */ + GPIO_InitStruct.Pin = M2_PWM1_Pin|M2_PWM2_Pin|M1_PWM1_Pin|M1_PWM2_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USER CODE BEGIN TIM1_MspPostInit 1 */ + + /* USER CODE END TIM1_MspPostInit 1 */ + } + else if(htim->Instance==TIM2) + { + /* USER CODE BEGIN TIM2_MspPostInit 0 */ + + /* USER CODE END TIM2_MspPostInit 0 */ + + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**TIM2 GPIO Configuration + PB10 ------> TIM2_CH3 + PB11 ------> TIM2_CH4 + PA15 ------> TIM2_CH1 + PB3 ------> TIM2_CH2 + */ + GPIO_InitStruct.Pin = SERVO3_Pin|SERVO4_Pin|SERVO2_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = SERVO1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(SERVO1_GPIO_Port, &GPIO_InitStruct); + + __HAL_AFIO_REMAP_TIM2_ENABLE(); + + /* USER CODE BEGIN TIM2_MspPostInit 1 */ + + /* USER CODE END TIM2_MspPostInit 1 */ + } + else if(htim->Instance==TIM3) + { + /* USER CODE BEGIN TIM3_MspPostInit 0 */ + + /* USER CODE END TIM3_MspPostInit 0 */ + + __HAL_RCC_GPIOB_CLK_ENABLE(); + /**TIM3 GPIO Configuration + PB4 ------> TIM3_CH1 + */ + GPIO_InitStruct.Pin = GPIO_PIN_4; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + __HAL_AFIO_REMAP_TIM3_PARTIAL(); + + /* USER CODE BEGIN TIM3_MspPostInit 1 */ + + /* USER CODE END TIM3_MspPostInit 1 */ + } + +} +/** +* @brief TIM_Base MSP De-Initialization +* This function freeze the hardware resources used in this example +* @param htim_base: TIM_Base handle pointer +* @retval None +*/ +void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base) +{ + if(htim_base->Instance==TIM1) + { + /* USER CODE BEGIN TIM1_MspDeInit 0 */ + + /* USER CODE END TIM1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_TIM1_CLK_DISABLE(); + /* USER CODE BEGIN TIM1_MspDeInit 1 */ + + /* USER CODE END TIM1_MspDeInit 1 */ + } + else if(htim_base->Instance==TIM2) + { + /* USER CODE BEGIN TIM2_MspDeInit 0 */ + + /* USER CODE END TIM2_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_TIM2_CLK_DISABLE(); + /* USER CODE BEGIN TIM2_MspDeInit 1 */ + + /* USER CODE END TIM2_MspDeInit 1 */ + } + +} + +/** +* @brief TIM_PWM MSP De-Initialization +* This function freeze the hardware resources used in this example +* @param htim_pwm: TIM_PWM handle pointer +* @retval None +*/ +void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* htim_pwm) +{ + if(htim_pwm->Instance==TIM3) + { + /* USER CODE BEGIN TIM3_MspDeInit 0 */ + + /* USER CODE END TIM3_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_TIM3_CLK_DISABLE(); + /* USER CODE BEGIN TIM3_MspDeInit 1 */ + + /* USER CODE END TIM3_MspDeInit 1 */ + } + +} + +/** +* @brief UART MSP Initialization +* This function configures the hardware resources used in this example +* @param huart: UART handle pointer +* @retval None +*/ +void HAL_UART_MspInit(UART_HandleTypeDef* huart) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(huart->Instance==USART2) + { + /* USER CODE BEGIN USART2_MspInit 0 */ + + /* USER CODE END USART2_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_USART2_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**USART2 GPIO Configuration + PA2 ------> USART2_TX + PA3 ------> USART2_RX + */ + GPIO_InitStruct.Pin = GPIO_PIN_2; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_3; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USART2 DMA Init */ + /* USART2_RX Init */ + hdma_usart2_rx.Instance = DMA1_Channel6; + hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_usart2_rx.Init.Mode = DMA_NORMAL; + hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW; + if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK) + { + Error_Handler(); + } + + __HAL_LINKDMA(huart,hdmarx,hdma_usart2_rx); + + /* USER CODE BEGIN USART2_MspInit 1 */ + + /* USER CODE END USART2_MspInit 1 */ + } + +} + +/** +* @brief UART MSP De-Initialization +* This function freeze the hardware resources used in this example +* @param huart: UART handle pointer +* @retval None +*/ +void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) +{ + if(huart->Instance==USART2) + { + /* USER CODE BEGIN USART2_MspDeInit 0 */ + + /* USER CODE END USART2_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USART2_CLK_DISABLE(); + + /**USART2 GPIO Configuration + PA2 ------> USART2_TX + PA3 ------> USART2_RX + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); + + /* USART2 DMA DeInit */ + HAL_DMA_DeInit(huart->hdmarx); + + /* USART2 interrupt DeInit */ + HAL_NVIC_DisableIRQ(USART2_IRQn); + /* USER CODE BEGIN USART2_MspDeInit 1 */ + + /* USER CODE END USART2_MspDeInit 1 */ + } + +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/src/stm32/Core/Src/stm32f1xx_it.c b/src/stm32/Core/Src/stm32f1xx_it.c new file mode 100644 index 0000000..025cd4e --- /dev/null +++ b/src/stm32/Core/Src/stm32f1xx_it.c @@ -0,0 +1,238 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f1xx_it.c + * @brief Interrupt Service Routines. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "stm32f1xx_it.h" +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN TD */ + +/* USER CODE END TD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ +extern uint32_t time_from_last_command; +extern const uint32_t uart_timeout; +extern uint8_t emergency_stop; + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* External variables --------------------------------------------------------*/ +extern DMA_HandleTypeDef hdma_usart2_rx; +extern UART_HandleTypeDef huart2; +/* USER CODE BEGIN EV */ + +/* USER CODE END EV */ + +/******************************************************************************/ +/* Cortex-M3 Processor Interruption and Exception Handlers */ +/******************************************************************************/ +/** + * @brief This function handles Non maskable interrupt. + */ +void NMI_Handler(void) +{ + /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ + + /* USER CODE END NonMaskableInt_IRQn 0 */ + /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ + while (1) { + } + /* USER CODE END NonMaskableInt_IRQn 1 */ +} + +/** + * @brief This function handles Hard fault interrupt. + */ +void HardFault_Handler(void) +{ + /* USER CODE BEGIN HardFault_IRQn 0 */ + + /* USER CODE END HardFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_HardFault_IRQn 0 */ + /* USER CODE END W1_HardFault_IRQn 0 */ + } +} + +/** + * @brief This function handles Memory management fault. + */ +void MemManage_Handler(void) +{ + /* USER CODE BEGIN MemoryManagement_IRQn 0 */ + + /* USER CODE END MemoryManagement_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ + /* USER CODE END W1_MemoryManagement_IRQn 0 */ + } +} + +/** + * @brief This function handles Prefetch fault, memory access fault. + */ +void BusFault_Handler(void) +{ + /* USER CODE BEGIN BusFault_IRQn 0 */ + + /* USER CODE END BusFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_BusFault_IRQn 0 */ + /* USER CODE END W1_BusFault_IRQn 0 */ + } +} + +/** + * @brief This function handles Undefined instruction or illegal state. + */ +void UsageFault_Handler(void) +{ + /* USER CODE BEGIN UsageFault_IRQn 0 */ + + /* USER CODE END UsageFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ + /* USER CODE END W1_UsageFault_IRQn 0 */ + } +} + +/** + * @brief This function handles System service call via SWI instruction. + */ +void SVC_Handler(void) +{ + /* USER CODE BEGIN SVCall_IRQn 0 */ + + /* USER CODE END SVCall_IRQn 0 */ + /* USER CODE BEGIN SVCall_IRQn 1 */ + + /* USER CODE END SVCall_IRQn 1 */ +} + +/** + * @brief This function handles Debug monitor. + */ +void DebugMon_Handler(void) +{ + /* USER CODE BEGIN DebugMonitor_IRQn 0 */ + + /* USER CODE END DebugMonitor_IRQn 0 */ + /* USER CODE BEGIN DebugMonitor_IRQn 1 */ + + /* USER CODE END DebugMonitor_IRQn 1 */ +} + +/** + * @brief This function handles Pendable request for system service. + */ +void PendSV_Handler(void) +{ + /* USER CODE BEGIN PendSV_IRQn 0 */ + + /* USER CODE END PendSV_IRQn 0 */ + /* USER CODE BEGIN PendSV_IRQn 1 */ + + /* USER CODE END PendSV_IRQn 1 */ +} + +/** + * @brief This function handles System tick timer. + */ +void SysTick_Handler(void) +{ + /* USER CODE BEGIN SysTick_IRQn 0 */ + if (time_from_last_command < uart_timeout) + time_from_last_command++; + else + emergency_stop = 1; + + /* USER CODE END SysTick_IRQn 0 */ + HAL_IncTick(); + /* USER CODE BEGIN SysTick_IRQn 1 */ + + /* USER CODE END SysTick_IRQn 1 */ +} + +/******************************************************************************/ +/* STM32F1xx Peripheral Interrupt Handlers */ +/* Add here the Interrupt Handlers for the used peripherals. */ +/* For the available peripheral interrupt handler names, */ +/* please refer to the startup file (startup_stm32f1xx.s). */ +/******************************************************************************/ + +/** + * @brief This function handles DMA1 channel6 global interrupt. + */ +void DMA1_Channel6_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Channel6_IRQn 0 */ + + /* USER CODE END DMA1_Channel6_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_usart2_rx); + /* USER CODE BEGIN DMA1_Channel6_IRQn 1 */ + + /* USER CODE END DMA1_Channel6_IRQn 1 */ +} + +/** + * @brief This function handles USART2 global interrupt. + */ +void USART2_IRQHandler(void) +{ + /* USER CODE BEGIN USART2_IRQn 0 */ + + /* USER CODE END USART2_IRQn 0 */ + HAL_UART_IRQHandler(&huart2); + /* USER CODE BEGIN USART2_IRQn 1 */ + + /* USER CODE END USART2_IRQn 1 */ +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/src/stm32/Core/Src/syscalls.c b/src/stm32/Core/Src/syscalls.c new file mode 100644 index 0000000..d190edf --- /dev/null +++ b/src/stm32/Core/Src/syscalls.c @@ -0,0 +1,176 @@ +/** + ****************************************************************************** + * @file syscalls.c + * @author Auto-generated by STM32CubeIDE + * @brief STM32CubeIDE Minimal System calls file + * + * For more information about which c-functions + * need which of these lowlevel functions + * please consult the Newlib libc-manual + ****************************************************************************** + * @attention + * + * Copyright (c) 2020-2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Variables */ +extern int __io_putchar(int ch) __attribute__((weak)); +extern int __io_getchar(void) __attribute__((weak)); + + +char *__env[1] = { 0 }; +char **environ = __env; + + +/* Functions */ +void initialise_monitor_handles() +{ +} + +int _getpid(void) +{ + return 1; +} + +int _kill(int pid, int sig) +{ + (void)pid; + (void)sig; + errno = EINVAL; + return -1; +} + +void _exit (int status) +{ + _kill(status, -1); + while (1) {} /* Make sure we hang here */ +} + +__attribute__((weak)) int _read(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + *ptr++ = __io_getchar(); + } + + return len; +} + +__attribute__((weak)) int _write(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + __io_putchar(*ptr++); + } + return len; +} + +int _close(int file) +{ + (void)file; + return -1; +} + + +int _fstat(int file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) +{ + (void)file; + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + (void)file; + (void)ptr; + (void)dir; + return 0; +} + +int _open(char *path, int flags, ...) +{ + (void)path; + (void)flags; + /* Pretend like we always fail */ + return -1; +} + +int _wait(int *status) +{ + (void)status; + errno = ECHILD; + return -1; +} + +int _unlink(char *name) +{ + (void)name; + errno = ENOENT; + return -1; +} + +int _times(struct tms *buf) +{ + (void)buf; + return -1; +} + +int _stat(char *file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _link(char *old, char *new) +{ + (void)old; + (void)new; + errno = EMLINK; + return -1; +} + +int _fork(void) +{ + errno = EAGAIN; + return -1; +} + +int _execve(char *name, char **argv, char **env) +{ + (void)name; + (void)argv; + (void)env; + errno = ENOMEM; + return -1; +} diff --git a/src/stm32/Core/Src/sysmem.c b/src/stm32/Core/Src/sysmem.c new file mode 100644 index 0000000..921ecef --- /dev/null +++ b/src/stm32/Core/Src/sysmem.c @@ -0,0 +1,79 @@ +/** + ****************************************************************************** + * @file sysmem.c + * @author Generated by STM32CubeIDE + * @brief STM32CubeIDE System Memory calls file + * + * For more information about which C functions + * need which of these lowlevel functions + * please consult the newlib libc manual + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes */ +#include +#include + +/** + * Pointer to the current high watermark of the heap usage + */ +static uint8_t *__sbrk_heap_end = NULL; + +/** + * @brief _sbrk() allocates memory to the newlib heap and is used by malloc + * and others from the C library + * + * @verbatim + * ############################################################################ + * # .data # .bss # newlib heap # MSP stack # + * # # # # Reserved by _Min_Stack_Size # + * ############################################################################ + * ^-- RAM start ^-- _end _estack, RAM end --^ + * @endverbatim + * + * This implementation starts allocating at the '_end' linker symbol + * The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack + * The implementation considers '_estack' linker symbol to be RAM end + * NOTE: If the MSP stack, at any point during execution, grows larger than the + * reserved size, please increase the '_Min_Stack_Size'. + * + * @param incr Memory size + * @return Pointer to allocated memory + */ +void *_sbrk(ptrdiff_t incr) +{ + extern uint8_t _end; /* Symbol defined in the linker script */ + extern uint8_t _estack; /* Symbol defined in the linker script */ + extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */ + const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size; + const uint8_t *max_heap = (uint8_t *)stack_limit; + uint8_t *prev_heap_end; + + /* Initialize heap end at first call */ + if (NULL == __sbrk_heap_end) + { + __sbrk_heap_end = &_end; + } + + /* Protect heap from growing into the reserved MSP stack */ + if (__sbrk_heap_end + incr > max_heap) + { + errno = ENOMEM; + return (void *)-1; + } + + prev_heap_end = __sbrk_heap_end; + __sbrk_heap_end += incr; + + return (void *)prev_heap_end; +} diff --git a/src/stm32/Core/Src/system_stm32f1xx.c b/src/stm32/Core/Src/system_stm32f1xx.c new file mode 100644 index 0000000..3e277e6 --- /dev/null +++ b/src/stm32/Core/Src/system_stm32f1xx.c @@ -0,0 +1,406 @@ +/** + ****************************************************************************** + * @file system_stm32f1xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File. + * + * 1. This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier + * factors, AHB/APBx prescalers and Flash settings). + * This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f1xx_xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * 2. After each device reset the HSI (8 MHz) is used as system clock source. + * Then SystemInit() function is called, in "startup_stm32f1xx_xx.s" file, to + * configure the system clock before to branch to main program. + * + * 4. The default value of HSE crystal is set to 8 MHz (or 25 MHz, depending on + * the product used), refer to "HSE_VALUE". + * When HSE is used as system clock source, directly or through PLL, and you + * are using different crystal you have to adapt the HSE value to your own + * configuration. + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017-2021 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f1xx_system + * @{ + */ + +/** @addtogroup STM32F1xx_System_Private_Includes + * @{ + */ + +#include "stm32f1xx.h" + +/** + * @} + */ + +/** @addtogroup STM32F1xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F1xx_System_Private_Defines + * @{ + */ + +#if !defined (HSE_VALUE) + #define HSE_VALUE 8000000U /*!< Default value of the External oscillator in Hz. + This value can be provided and adapted by the user application. */ +#endif /* HSE_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE 8000000U /*!< Default value of the Internal oscillator in Hz. + This value can be provided and adapted by the user application. */ +#endif /* HSI_VALUE */ + +/*!< Uncomment the following line if you need to use external SRAM */ +#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) +/* #define DATA_IN_ExtSRAM */ +#endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ + +/* Note: Following vector table addresses must be defined in line with linker + configuration. */ +/*!< Uncomment the following line if you need to relocate the vector table + anywhere in Flash or Sram, else the vector table is kept at the automatic + remap of boot address selected */ +/* #define USER_VECT_TAB_ADDRESS */ + +#if defined(USER_VECT_TAB_ADDRESS) +/*!< Uncomment the following line if you need to relocate your vector Table + in Sram else user remap will be done in Flash. */ +/* #define VECT_TAB_SRAM */ +#if defined(VECT_TAB_SRAM) +#define VECT_TAB_BASE_ADDRESS SRAM_BASE /*!< Vector Table base address field. + This value must be a multiple of 0x200. */ +#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +#else +#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field. + This value must be a multiple of 0x200. */ +#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +#endif /* VECT_TAB_SRAM */ +#endif /* USER_VECT_TAB_ADDRESS */ + +/******************************************************************************/ + +/** + * @} + */ + +/** @addtogroup STM32F1xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F1xx_System_Private_Variables + * @{ + */ + + /* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ +uint32_t SystemCoreClock = 16000000; +const uint8_t AHBPrescTable[16U] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; +const uint8_t APBPrescTable[8U] = {0, 0, 0, 0, 1, 2, 3, 4}; + +/** + * @} + */ + +/** @addtogroup STM32F1xx_System_Private_FunctionPrototypes + * @{ + */ + +#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) +#ifdef DATA_IN_ExtSRAM + static void SystemInit_ExtMemCtl(void); +#endif /* DATA_IN_ExtSRAM */ +#endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ + +/** + * @} + */ + +/** @addtogroup STM32F1xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the Embedded Flash Interface, the PLL and update the + * SystemCoreClock variable. + * @note This function should be used only after reset. + * @param None + * @retval None + */ +void SystemInit (void) +{ +#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) + #ifdef DATA_IN_ExtSRAM + SystemInit_ExtMemCtl(); + #endif /* DATA_IN_ExtSRAM */ +#endif + + /* Configure the Vector Table location -------------------------------------*/ +#if defined(USER_VECT_TAB_ADDRESS) + SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */ +#endif /* USER_VECT_TAB_ADDRESS */ +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f1xx.h file (default value + * 8 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f1xx.h file (default value + * 8 MHz or 25 MHz, depending on the product used), user has to ensure + * that HSE_VALUE is same as the real frequency of the crystal used. + * Otherwise, this function may have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * @param None + * @retval None + */ +void SystemCoreClockUpdate (void) +{ + uint32_t tmp = 0U, pllmull = 0U, pllsource = 0U; + +#if defined(STM32F105xC) || defined(STM32F107xC) + uint32_t prediv1source = 0U, prediv1factor = 0U, prediv2factor = 0U, pll2mull = 0U; +#endif /* STM32F105xC */ + +#if defined(STM32F100xB) || defined(STM32F100xE) + uint32_t prediv1factor = 0U; +#endif /* STM32F100xB or STM32F100xE */ + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00U: /* HSI used as system clock */ + SystemCoreClock = HSI_VALUE; + break; + case 0x04U: /* HSE used as system clock */ + SystemCoreClock = HSE_VALUE; + break; + case 0x08U: /* PLL used as system clock */ + + /* Get PLL clock source and multiplication factor ----------------------*/ + pllmull = RCC->CFGR & RCC_CFGR_PLLMULL; + pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; + +#if !defined(STM32F105xC) && !defined(STM32F107xC) + pllmull = ( pllmull >> 18U) + 2U; + + if (pllsource == 0x00U) + { + /* HSI oscillator clock divided by 2 selected as PLL clock entry */ + SystemCoreClock = (HSI_VALUE >> 1U) * pllmull; + } + else + { + #if defined(STM32F100xB) || defined(STM32F100xE) + prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1U; + /* HSE oscillator clock selected as PREDIV1 clock entry */ + SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; + #else + /* HSE selected as PLL clock entry */ + if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET) + {/* HSE oscillator clock divided by 2 */ + SystemCoreClock = (HSE_VALUE >> 1U) * pllmull; + } + else + { + SystemCoreClock = HSE_VALUE * pllmull; + } + #endif + } +#else + pllmull = pllmull >> 18U; + + if (pllmull != 0x0DU) + { + pllmull += 2U; + } + else + { /* PLL multiplication factor = PLL input clock * 6.5 */ + pllmull = 13U / 2U; + } + + if (pllsource == 0x00U) + { + /* HSI oscillator clock divided by 2 selected as PLL clock entry */ + SystemCoreClock = (HSI_VALUE >> 1U) * pllmull; + } + else + {/* PREDIV1 selected as PLL clock entry */ + + /* Get PREDIV1 clock source and division factor */ + prediv1source = RCC->CFGR2 & RCC_CFGR2_PREDIV1SRC; + prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1U; + + if (prediv1source == 0U) + { + /* HSE oscillator clock selected as PREDIV1 clock entry */ + SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; + } + else + {/* PLL2 clock selected as PREDIV1 clock entry */ + + /* Get PREDIV2 division factor and PLL2 multiplication factor */ + prediv2factor = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> 4U) + 1U; + pll2mull = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> 8U) + 2U; + SystemCoreClock = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull; + } + } +#endif /* STM32F105xC */ + break; + + default: + SystemCoreClock = HSI_VALUE; + break; + } + + /* Compute HCLK clock frequency ----------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)]; + /* HCLK clock frequency */ + SystemCoreClock >>= tmp; +} + +#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) +/** + * @brief Setup the external memory controller. Called in startup_stm32f1xx.s + * before jump to __main + * @param None + * @retval None + */ +#ifdef DATA_IN_ExtSRAM +/** + * @brief Setup the external memory controller. + * Called in startup_stm32f1xx_xx.s/.c before jump to main. + * This function configures the external SRAM mounted on STM3210E-EVAL + * board (STM32 High density devices). This SRAM will be used as program + * data memory (including heap and stack). + * @param None + * @retval None + */ +void SystemInit_ExtMemCtl(void) +{ + __IO uint32_t tmpreg; + /*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is + required, then adjust the Register Addresses */ + + /* Enable FSMC clock */ + RCC->AHBENR = 0x00000114U; + + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->AHBENR, RCC_AHBENR_FSMCEN); + + /* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */ + RCC->APB2ENR = 0x000001E0U; + + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPDEN); + + (void)(tmpreg); + +/* --------------- SRAM Data lines, NOE and NWE configuration ---------------*/ +/*---------------- SRAM Address lines configuration -------------------------*/ +/*---------------- NOE and NWE configuration --------------------------------*/ +/*---------------- NE3 configuration ----------------------------------------*/ +/*---------------- NBL0, NBL1 configuration ---------------------------------*/ + + GPIOD->CRL = 0x44BB44BBU; + GPIOD->CRH = 0xBBBBBBBBU; + + GPIOE->CRL = 0xB44444BBU; + GPIOE->CRH = 0xBBBBBBBBU; + + GPIOF->CRL = 0x44BBBBBBU; + GPIOF->CRH = 0xBBBB4444U; + + GPIOG->CRL = 0x44BBBBBBU; + GPIOG->CRH = 0x444B4B44U; + +/*---------------- FSMC Configuration ---------------------------------------*/ +/*---------------- Enable FSMC Bank1_SRAM Bank ------------------------------*/ + + FSMC_Bank1->BTCR[4U] = 0x00001091U; + FSMC_Bank1->BTCR[5U] = 0x00110212U; +} +#endif /* DATA_IN_ExtSRAM */ +#endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/stm32/Core/Src/user_logic.cpp b/src/stm32/Core/Src/user_logic.cpp new file mode 100644 index 0000000..ffe4f04 --- /dev/null +++ b/src/stm32/Core/Src/user_logic.cpp @@ -0,0 +1,234 @@ +#include +#include + +#ifdef HOST_BUILD +#include +#include +// Stuff needed for unit testing on host +class MotorsMock { +public: + uint8_t left1; + uint8_t left2; + uint8_t right1; + uint8_t right2; + bool standby = 0; + void reset() { + left1 = 0; + left2 = 0; + right1 = 0; + right2 = 0; + } +}; + +MotorsMock motors; + +#define Left1 (motors.left1) +#define Left2 (motors.left2) + +#define Right1 (motors.right1) +#define Right2 (motors.right2) + +#define STBY_ON() motors.standby = 1 +#define STBY_OFF() motors.standby = 1 + +#define HAL_GPIO_WritePin(a, b, c) ; +uint16_t servos[6]; + +#define SERVO(n) servos[n - 1] + +#else +// Stuff needed on STM32 +#include "main.h" +#include "user_logic.h" +#define Left1 TIM1->CCR3 +#define Left2 TIM1->CCR4 + +#define Right1 TIM1->CCR1 +#define Right2 TIM1->CCR2 +#define SERVO(n) *((uint32_t *)(&TIM2->CCR1) + n - 1) + +extern char usart2_buffer[256]; +void processCmd(etl::string_view view); + +void process() { + etl::string_ext text(usart2_buffer, usart2_buffer, etl::size(usart2_buffer)); + etl::string_view view(text); + processCmd(view); + return; +} +#endif + +constexpr const int max_speed = 70; + +void left_set_speed(int8_t speed); +void right_set_speed(int8_t speed); + +struct ServoPos { + uint8_t n; + uint8_t pos; +}; + +void servo_set_angle(uint8_t n, uint8_t angle); + +// CMD,S,1,90 + +void processCmd(etl::string_view view) { + etl::optional left_speed = etl::nullopt, right_speed = etl::nullopt; + etl::optional servo_cmd; + if (!view.starts_with("CMD,")) + return; + view.remove_prefix(4); + bool anything_left{true}; + while (anything_left) { + if (view.starts_with("L,")) { + view.remove_prefix(2); + size_t pos = view.find(","); + etl::string_view number; + if (pos != etl::string_view::npos) + number = view.substr(0, pos); + else + number = view; + left_speed = etl::to_arithmetic(number); + view.remove_prefix(pos + 1); + } + if (view.starts_with("S,")) { + uint8_t n = 0, servo_angle = 0; + view.remove_prefix(2); + const auto servo_n = view.at(0); + if (servo_n <= '6' && servo_n >= '1') + n = servo_n - '0'; + if (view.at(1) == ',') + view.remove_prefix(2); + + size_t pos = view.find(","); + etl::string_view found_angle; + if (pos != etl::string_view::npos) + found_angle = view.substr(0, pos); + else + found_angle = view; + servo_angle = etl::to_arithmetic(found_angle); + servo_set_angle(n, servo_angle); + } + if (view.starts_with("R,")) { + view.remove_prefix(2); + size_t pos = view.find(","); + etl::string_view number; + if (pos != etl::string_view::npos) + number = view.substr(0, pos); + else + number = view; + right_speed = etl::to_arithmetic(number); + view.remove_prefix(pos + 1); + } + if (view.starts_with("\r\n")) { + view.remove_prefix(2); + } + if (view.find(",") == etl::string_view::npos) + anything_left = false; + } + + if (left_speed != etl::nullopt) + left_set_speed(*left_speed); + + if (right_speed != etl::nullopt) + right_set_speed(*right_speed); +} + +void left_set_speed(int8_t speed) { + if (speed > 0) { + // clockwise + HAL_GPIO_WritePin(M1_IN1_GPIO_Port, M1_IN1_Pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(M1_IN2_GPIO_Port, M1_IN2_Pin, GPIO_PIN_RESET); + } else { + // counter - clockwise + HAL_GPIO_WritePin(M1_IN1_GPIO_Port, M1_IN1_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(M1_IN2_GPIO_Port, M1_IN2_Pin, GPIO_PIN_SET); + } + speed = abs(speed); + if (speed > max_speed) + speed = max_speed; + Left1 = speed; + Left2 = speed; + STBY_OFF(); +} + +void right_set_speed(int8_t speed) { + if (speed > 0) { + // clockwise + HAL_GPIO_WritePin(M2_IN1_GPIO_Port, M2_IN1_Pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(M2_IN2_GPIO_Port, M2_IN2_Pin, GPIO_PIN_RESET); + } else { + // counter - clockwise + HAL_GPIO_WritePin(M2_IN1_GPIO_Port, M2_IN1_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(M2_IN2_GPIO_Port, M2_IN2_Pin, GPIO_PIN_SET); + } + speed = abs(speed); + if (speed > max_speed) + speed = max_speed; + Right1 = speed; + Right2 = speed; + STBY_OFF(); +} + +void stop_motors() { + STBY_ON(); + Left1 = 0; + Left2 = 0; + Right1 = 0; + Right2 = 0; +} + +void servo_set_angle(uint8_t n, uint8_t angle) { + if (n > 4 && n) + return; + SERVO(n) = angle; +} + +#ifdef HOST_BUILD + +TEST(Speed, Maximum) { + motors.reset(); + ASSERT_EQ(motors.left1, 0); + ASSERT_EQ(motors.left2, 0); + processCmd("CMD,L,90"); + ASSERT_EQ(motors.left1, max_speed); + ASSERT_EQ(motors.left2, max_speed); +} + +TEST(Speed, Normal) { + motors.reset(); + ASSERT_EQ(motors.left1, 0); + ASSERT_EQ(motors.left2, 0); + processCmd("CMD,L,55"); + ASSERT_EQ(motors.left1, 55); + ASSERT_EQ(motors.left2, 55); + +} + +TEST(Servo, Normal) { + SERVO(1) = 0; + ASSERT_EQ(SERVO(1), 0); + processCmd("CMD,S,1,20"); + ASSERT_EQ(SERVO(1), 20); +} + +TEST(Servo, TooBig) { + SERVO(1) = 0; + ASSERT_EQ(SERVO(1), 0); + processCmd("CMD,S,1,320"); + ASSERT_EQ(SERVO(1), 0); +} + +TEST(Servo, Negative) { + SERVO(1) = 0; + ASSERT_EQ(SERVO(1), 0); + processCmd("CMD,S,1,-30"); + ASSERT_EQ(SERVO(1), 0); +} + +int main() { + testing::InitGoogleTest(); + (void)RUN_ALL_TESTS(); +} + +#endif // DEBUG diff --git a/src/stm32/Core/Startup/startup_stm32f103c6tx.s b/src/stm32/Core/Startup/startup_stm32f103c6tx.s new file mode 100644 index 0000000..87ca9ca --- /dev/null +++ b/src/stm32/Core/Startup/startup_stm32f103c6tx.s @@ -0,0 +1,348 @@ +/** + *************** (C) COPYRIGHT 2017 STMicroelectronics ************************ + * @file startup_stm32f103x6.s + * @author MCD Application Team + * @brief STM32F103x6 Devices vector table for Atollic toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Configure the clock system + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M3 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017-2021 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m3 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss + +.equ BootRAM, 0xF108F85F +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + +/* Call the clock system initialization function.*/ + bl SystemInit + +/* Copy the data segment initializers from flash to SRAM */ + ldr r0, =_sdata + ldr r1, =_edata + ldr r2, =_sidata + movs r3, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +LoopCopyDataInit: + adds r4, r0, r3 + cmp r4, r1 + bcc CopyDataInit + +/* Zero fill the bss segment. */ + ldr r2, =_sbss + ldr r4, =_ebss + movs r3, #0 + b LoopFillZerobss + +FillZerobss: + str r3, [r2] + adds r2, r2, #4 + +LoopFillZerobss: + cmp r2, r4 + bcc FillZerobss + +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * + * @param None + * @retval : None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M3. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + .word WWDG_IRQHandler + .word PVD_IRQHandler + .word TAMPER_IRQHandler + .word RTC_IRQHandler + .word FLASH_IRQHandler + .word RCC_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word DMA1_Channel5_IRQHandler + .word DMA1_Channel6_IRQHandler + .word DMA1_Channel7_IRQHandler + .word ADC1_2_IRQHandler + .word USB_HP_CAN1_TX_IRQHandler + .word USB_LP_CAN1_RX0_IRQHandler + .word CAN1_RX1_IRQHandler + .word CAN1_SCE_IRQHandler + .word EXTI9_5_IRQHandler + .word TIM1_BRK_IRQHandler + .word TIM1_UP_IRQHandler + .word TIM1_TRG_COM_IRQHandler + .word TIM1_CC_IRQHandler + .word TIM2_IRQHandler + .word TIM3_IRQHandler + .word 0 + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word 0 + .word 0 + .word SPI1_IRQHandler + .word 0 + .word USART1_IRQHandler + .word USART2_IRQHandler + .word 0 + .word EXTI15_10_IRQHandler + .word RTC_Alarm_IRQHandler + .word USBWakeUp_IRQHandler + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word BootRAM /* @0x108. This is for boot in RAM mode for + STM32F10x Low Density devices.*/ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMPER_IRQHandler + .thumb_set TAMPER_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + + .weak DMA1_Channel2_IRQHandler + .thumb_set DMA1_Channel2_IRQHandler,Default_Handler + + .weak DMA1_Channel3_IRQHandler + .thumb_set DMA1_Channel3_IRQHandler,Default_Handler + + .weak DMA1_Channel4_IRQHandler + .thumb_set DMA1_Channel4_IRQHandler,Default_Handler + + .weak DMA1_Channel5_IRQHandler + .thumb_set DMA1_Channel5_IRQHandler,Default_Handler + + .weak DMA1_Channel6_IRQHandler + .thumb_set DMA1_Channel6_IRQHandler,Default_Handler + + .weak DMA1_Channel7_IRQHandler + .thumb_set DMA1_Channel7_IRQHandler,Default_Handler + + .weak ADC1_2_IRQHandler + .thumb_set ADC1_2_IRQHandler,Default_Handler + + .weak USB_HP_CAN1_TX_IRQHandler + .thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler + + .weak USB_LP_CAN1_RX0_IRQHandler + .thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_IRQHandler + .thumb_set TIM1_BRK_IRQHandler,Default_Handler + + .weak TIM1_UP_IRQHandler + .thumb_set TIM1_UP_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_IRQHandler + .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak USBWakeUp_IRQHandler + .thumb_set USBWakeUp_IRQHandler,Default_Handler + diff --git a/src/stm32/README.md b/src/stm32/README.md new file mode 100644 index 0000000..c869b08 --- /dev/null +++ b/src/stm32/README.md @@ -0,0 +1,13 @@ +## STM32 + +This place holds the code that is used for MCU. + +In order to get the HAL libraries, just open the project in STM32CubeIDE and generate the code. + +### Unit testing + +Basic unit tests are availabe for command parser. +To execute them run: +```bash +cd testroot && mkcd build && cmake .. && make && ./ut +``` diff --git a/src/stm32/STM32F103C6TX_FLASH.ld b/src/stm32/STM32F103C6TX_FLASH.ld new file mode 100644 index 0000000..50eb53c --- /dev/null +++ b/src/stm32/STM32F103C6TX_FLASH.ld @@ -0,0 +1,185 @@ +/* +****************************************************************************** +** +** @file : LinkerScript.ld +** +** @author : Auto-generated by STM32CubeIDE +** +** @brief : Linker script for STM32F103C6Tx Device from STM32F1 series +** 32Kbytes FLASH +** 10Kbytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +****************************************************************************** +** @attention +** +** Copyright (c) 2023 STMicroelectronics. +** All rights reserved. +** +** This software is licensed under terms that can be found in the LICENSE file +** in the root directory of this software component. +** If no LICENSE file comes with this software, it is provided AS-IS. +** +****************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ + +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Memories definition */ +MEMORY +{ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 10K + FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K +} + +/* Sections */ +SECTIONS +{ + /* The startup code into "FLASH" Rom type memory */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data into "FLASH" Rom type memory */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data into "FLASH" Rom type memory */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >FLASH + + .ARM : { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >FLASH + + .preinit_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >FLASH + + .init_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >FLASH + + .fini_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >FLASH + + /* Used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections into "RAM" Ram type memory */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + + } >RAM AT> FLASH + + /* Uninitialized data section into "RAM" Ram type memory */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + /* Remove information from the compiler libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/src/stm32/f103-robotics.ioc b/src/stm32/f103-robotics.ioc new file mode 100644 index 0000000..75d0fd5 --- /dev/null +++ b/src/stm32/f103-robotics.ioc @@ -0,0 +1,253 @@ +#MicroXplorer Configuration settings - do not modify +ADC1.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_1 +ADC1.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,NbrOfConversionFlag,master +ADC1.NbrOfConversionFlag=1 +ADC1.Rank-0\#ChannelRegularConversion=1 +ADC1.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_1CYCLE_5 +ADC1.master=1 +CAD.formats= +CAD.pinconfig= +CAD.provider= +Dma.Request0=USART2_RX +Dma.RequestsNb=1 +Dma.USART2_RX.0.Direction=DMA_PERIPH_TO_MEMORY +Dma.USART2_RX.0.Instance=DMA1_Channel6 +Dma.USART2_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.USART2_RX.0.MemInc=DMA_MINC_ENABLE +Dma.USART2_RX.0.Mode=DMA_NORMAL +Dma.USART2_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.USART2_RX.0.PeriphInc=DMA_PINC_DISABLE +Dma.USART2_RX.0.Priority=DMA_PRIORITY_LOW +Dma.USART2_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +File.Version=6 +KeepUserPlacement=false +Mcu.CPN=STM32F103C6T6A +Mcu.Family=STM32F1 +Mcu.IP0=ADC1 +Mcu.IP1=DMA +Mcu.IP2=NVIC +Mcu.IP3=RCC +Mcu.IP4=SYS +Mcu.IP5=TIM1 +Mcu.IP6=TIM2 +Mcu.IP7=TIM3 +Mcu.IP8=USART2 +Mcu.IPNb=9 +Mcu.Name=STM32F103C(4-6)Tx +Mcu.Package=LQFP48 +Mcu.Pin0=PA0-WKUP +Mcu.Pin1=PA1 +Mcu.Pin10=PA8 +Mcu.Pin11=PA9 +Mcu.Pin12=PA10 +Mcu.Pin13=PA11 +Mcu.Pin14=PA12 +Mcu.Pin15=PA13 +Mcu.Pin16=PA14 +Mcu.Pin17=PA15 +Mcu.Pin18=PB3 +Mcu.Pin19=PB4 +Mcu.Pin2=PA2 +Mcu.Pin20=PB8 +Mcu.Pin21=PB9 +Mcu.Pin22=VP_TIM1_VS_ClockSourceINT +Mcu.Pin23=VP_TIM2_VS_ClockSourceINT +Mcu.Pin3=PA3 +Mcu.Pin4=PB10 +Mcu.Pin5=PB11 +Mcu.Pin6=PB12 +Mcu.Pin7=PB13 +Mcu.Pin8=PB14 +Mcu.Pin9=PB15 +Mcu.PinsNb=24 +Mcu.ThirdPartyNb=0 +Mcu.UserConstants= +Mcu.UserName=STM32F103C6Tx +MxCube.Version=6.8.0 +MxDb.Version=DB.6.0.80 +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.DMA1_Channel6_IRQn=true\:0\:0\:false\:true\:true\:1\:false\:true\:true +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.ForceEnableDMAVector=true +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false +NVIC.USART2_IRQn=true\:0\:0\:false\:true\:true\:2\:true\:true\:true +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +PA0-WKUP.Locked=true +PA0-WKUP.Signal=ADCx_IN0 +PA1.Locked=true +PA1.Signal=ADCx_IN1 +PA10.GPIOParameters=GPIO_Label +PA10.GPIO_Label=M1_PWM1 +PA10.Signal=S_TIM1_CH3 +PA11.GPIOParameters=GPIO_Label +PA11.GPIO_Label=M1_PWM2 +PA11.Signal=S_TIM1_CH4 +PA12.GPIOParameters=GPIO_Label +PA12.GPIO_Label=STBY +PA12.Locked=true +PA12.Signal=GPIO_Output +PA13.Mode=Serial_Wire +PA13.Signal=SYS_JTMS-SWDIO +PA14.Mode=Serial_Wire +PA14.Signal=SYS_JTCK-SWCLK +PA15.GPIOParameters=GPIO_Label +PA15.GPIO_Label=SERVO1 +PA15.Locked=true +PA15.Signal=S_TIM2_CH1_ETR +PA2.Mode=Asynchronous +PA2.Signal=USART2_TX +PA3.Mode=Asynchronous +PA3.Signal=USART2_RX +PA8.GPIOParameters=GPIO_Label +PA8.GPIO_Label=M2_PWM1 +PA8.Locked=true +PA8.Signal=S_TIM1_CH1 +PA9.GPIOParameters=GPIO_Label +PA9.GPIO_Label=M2_PWM2 +PA9.Locked=true +PA9.Signal=S_TIM1_CH2 +PB10.GPIOParameters=GPIO_Label +PB10.GPIO_Label=SERVO3 +PB10.Locked=true +PB10.Signal=S_TIM2_CH3 +PB11.GPIOParameters=GPIO_Label +PB11.GPIO_Label=SERVO4 +PB11.Locked=true +PB11.Signal=S_TIM2_CH4 +PB12.GPIOParameters=GPIO_Label +PB12.GPIO_Label=M2_IN1 +PB12.Locked=true +PB12.Signal=GPIO_Output +PB13.GPIOParameters=GPIO_Label +PB13.GPIO_Label=M2_IN2 +PB13.Locked=true +PB13.Signal=GPIO_Output +PB14.GPIOParameters=GPIO_Label +PB14.GPIO_Label=M1_IN2 +PB14.Locked=true +PB14.Signal=GPIO_Output +PB15.GPIOParameters=GPIO_Label +PB15.GPIO_Label=M1_IN1 +PB15.Locked=true +PB15.Signal=GPIO_Output +PB3.GPIOParameters=GPIO_Label +PB3.GPIO_Label=SERVO2 +PB3.Locked=true +PB3.Signal=S_TIM2_CH2 +PB4.Locked=true +PB4.Signal=S_TIM3_CH1 +PB8.GPIOParameters=GPIO_Label +PB8.GPIO_Label=DBG_BTN +PB8.Locked=true +PB8.Signal=GPIO_Input +PB9.GPIOParameters=GPIO_Label +PB9.GPIO_Label=DBG_LED +PB9.Locked=true +PB9.Signal=GPIO_Output +PinOutPanel.RotationAngle=0 +ProjectManager.AskForMigrate=true +ProjectManager.BackupPrevious=false +ProjectManager.CompilerOptimize=6 +ProjectManager.ComputerToolchain=false +ProjectManager.CoupleFile=false +ProjectManager.CustomerFirmwarePackage= +ProjectManager.DefaultFWLocation=true +ProjectManager.DeletePrevious=true +ProjectManager.DeviceId=STM32F103C6Tx +ProjectManager.FirmwarePackage=STM32Cube FW_F1 V1.8.5 +ProjectManager.FreePins=false +ProjectManager.HalAssertFull=false +ProjectManager.HeapSize=0x200 +ProjectManager.KeepUserCode=true +ProjectManager.LastFirmware=true +ProjectManager.LibraryCopy=1 +ProjectManager.MainLocation=Core/Src +ProjectManager.NoMain=false +ProjectManager.PreviousToolchain= +ProjectManager.ProjectBuild=false +ProjectManager.ProjectFileName=f103-robotics.ioc +ProjectManager.ProjectName=f103-robotics +ProjectManager.ProjectStructure= +ProjectManager.RegisterCallBack= +ProjectManager.StackSize=0x400 +ProjectManager.TargetToolchain=STM32CubeIDE +ProjectManager.ToolChainLocation= +ProjectManager.UnderRoot=true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_USART2_UART_Init-USART2-false-HAL-true,5-MX_TIM2_Init-TIM2-false-HAL-true,6-MX_TIM3_Init-TIM3-false-HAL-true,7-MX_TIM1_Init-TIM1-false-HAL-true,8-MX_ADC1_Init-ADC1-false-HAL-true +RCC.ADCFreqValue=12000000 +RCC.AHBFreq_Value=48000000 +RCC.APB1CLKDivider=RCC_HCLK_DIV2 +RCC.APB1Freq_Value=24000000 +RCC.APB1TimFreq_Value=48000000 +RCC.APB2CLKDivider=RCC_HCLK_DIV2 +RCC.APB2Freq_Value=24000000 +RCC.APB2TimFreq_Value=48000000 +RCC.FCLKCortexFreq_Value=48000000 +RCC.FamilyName=M +RCC.HCLKFreq_Value=48000000 +RCC.IPParameters=ADCFreqValue,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,MCOFreq_Value,PLLCLKFreq_Value,PLLMCOFreq_Value,PLLMUL,SYSCLKFreq_VALUE,SYSCLKSource,TimSysFreq_Value,USBFreq_Value +RCC.MCOFreq_Value=48000000 +RCC.PLLCLKFreq_Value=48000000 +RCC.PLLMCOFreq_Value=24000000 +RCC.PLLMUL=RCC_PLL_MUL12 +RCC.SYSCLKFreq_VALUE=48000000 +RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK +RCC.TimSysFreq_Value=48000000 +RCC.USBFreq_Value=48000000 +SH.ADCx_IN0.0=ADC1_IN0,IN0 +SH.ADCx_IN0.ConfNb=1 +SH.ADCx_IN1.0=ADC1_IN1,IN1 +SH.ADCx_IN1.ConfNb=1 +SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1 +SH.S_TIM1_CH1.ConfNb=1 +SH.S_TIM1_CH2.0=TIM1_CH2,PWM Generation2 CH2 +SH.S_TIM1_CH2.ConfNb=1 +SH.S_TIM1_CH3.0=TIM1_CH3,PWM Generation3 CH3 +SH.S_TIM1_CH3.ConfNb=1 +SH.S_TIM1_CH4.0=TIM1_CH4,PWM Generation4 CH4 +SH.S_TIM1_CH4.ConfNb=1 +SH.S_TIM2_CH1_ETR.0=TIM2_CH1,PWM Generation1 CH1 +SH.S_TIM2_CH1_ETR.ConfNb=1 +SH.S_TIM2_CH2.0=TIM2_CH2,PWM Generation2 CH2 +SH.S_TIM2_CH2.ConfNb=1 +SH.S_TIM2_CH3.0=TIM2_CH3,PWM Generation3 CH3 +SH.S_TIM2_CH3.ConfNb=1 +SH.S_TIM2_CH4.0=TIM2_CH4,PWM Generation4 CH4 +SH.S_TIM2_CH4.ConfNb=1 +SH.S_TIM3_CH1.0=TIM3_CH1,PWM Generation1 CH1 +SH.S_TIM3_CH1.ConfNb=1 +TIM1.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE +TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1 +TIM1.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2 +TIM1.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3 +TIM1.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4 +TIM1.IPParameters=Prescaler,Period,AutoReloadPreload,Channel-PWM Generation3 CH3,Channel-PWM Generation4 CH4,Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2 +TIM1.Period=100 +TIM1.Prescaler=48-1 +TIM2.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE +TIM2.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1 +TIM2.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2 +TIM2.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3 +TIM2.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4 +TIM2.IPParameters=Channel-PWM Generation2 CH2,Prescaler,Period,AutoReloadPreload,Channel-PWM Generation1 CH1,Channel-PWM Generation3 CH3,Channel-PWM Generation4 CH4 +TIM2.Period=1800-1 +TIM2.Prescaler=532 +TIM3.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE +TIM3.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1 +TIM3.IPParameters=Channel-PWM Generation1 CH1,Prescaler,Period,AutoReloadPreload +TIM3.Period=100 +TIM3.Prescaler=48-1 +USART2.IPParameters=VirtualMode +USART2.VirtualMode=VM_ASYNC +VP_TIM1_VS_ClockSourceINT.Mode=Internal +VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT +VP_TIM2_VS_ClockSourceINT.Mode=Internal +VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT +board=custom +isbadioc=false diff --git a/src/stm32/testroot/CMakeLists.txt b/src/stm32/testroot/CMakeLists.txt new file mode 100644 index 0000000..477beeb --- /dev/null +++ b/src/stm32/testroot/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.16) +set(CMAKE_EXPORT_COMPILE_COMMANDS on) +project(ROBOTICS_UNIT_TESTS) +set(SRC + ../Core/Src/user_logic.cpp) + +add_executable(ut ${SRC}) +target_link_libraries(ut PRIVATE gtest pthread) +target_compile_definitions(ut PUBLIC HOST_BUILD)