diff --git a/.github/workflows/build-firmware.yml b/.github/workflows/build-firmware.yml deleted file mode 100644 index 22ff63a..0000000 --- a/.github/workflows/build-firmware.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Build Firmware - -on: [push] - -jobs: - build_and_test: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Build and run tests - run: | - sudo apt-get install -y sdcc cmake - cd ./Software/Firmware - sdcc --version - mkdir build_directory - cd build_directory - cmake -DCMAKE_SYSTEM_NAME=Generic -DCMAKE_C_COMPILER=sdcc .. - make VERBOSE=1 - - - name: Archive firmware binary - uses: actions/upload-artifact@v2 - if: always() - with: - name: Firmware binary - path: ./Software/Firmware/build_directory/IonizationChamber.ihx diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..451ec75 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,156 @@ +name: CI Pipeline + +on: + push: + branches: + - '*' + pull_request: + branches: + - '*' + +jobs: + run-c-static-analysis: + name: Run C Static Analysis + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Install Docker Compose + run: | + sudo apt-get update + sudo apt-get install -y docker-compose + + - name: Build and Start Docker Compose + run: | + docker-compose up -d --build + + - name: Run C Static Analysis + run: | + docker-compose exec -T app bash -c "dos2unix /workspace/ContinuousIntegration/run_c_static_code_analysis.sh && bash /workspace/ContinuousIntegration/run_c_static_code_analysis.sh" + + - name: Copy C Analysis Reports to Host + run: | + docker cp app:/workspace/build/C_Lint_ReportApplicationOnly.txt . + docker cp app:/workspace/build/C_Lint_ReportFull.txt . + + - name: Archive C Analysis Reports + uses: actions/upload-artifact@v3 + with: + name: c-lint-reports + path: | + C_Lint_ReportApplicationOnly.txt + C_Lint_ReportFull.txt + + - name: Clean Up Containers + run: | + docker-compose down + + run-python-static-analysis: + name: Run Python Static Analysis + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Install Docker Compose + run: | + sudo apt-get update + sudo apt-get install -y docker-compose + + - name: Build and Start Docker Compose + run: | + docker-compose up -d --build + + - name: Run Python Static Analysis + run: | + docker-compose exec -T app bash -c "dos2unix /workspace/ContinuousIntegration/run_python_static_code_analysis.sh && bash /workspace/ContinuousIntegration/run_python_static_code_analysis.sh" + + - name: Copy Python Analysis Reports to Host + run: | + docker cp app:/workspace/build/python_lint_report ./python_lint_report + + - name: Archive Python Analysis Reports + uses: actions/upload-artifact@v3 + with: + name: python-lint-reports + path: python_lint_report + + - name: Clean Up Containers + run: | + docker-compose down + + run-shell-static-analysis: + name: Run Shell Static Analysis + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Install Docker Compose + run: | + sudo apt-get update + sudo apt-get install -y docker-compose + + - name: Build and Start Docker Compose + run: | + docker-compose up -d --build + + - name: Run Shell Static Analysis + run: | + docker-compose exec -T app bash -c "dos2unix /workspace/ContinuousIntegration/run_shellscripts_static_code_analysis.sh && bash /workspace/ContinuousIntegration/run_shellscripts_static_code_analysis.sh" + + - name: Copy Shell Analysis Report to Host + run: | + docker cp app:/workspace/build/Shell_Script_Lint_Report.txt Shell_Script_Lint_Report.txt + + - name: Archive Shell Analysis Report + uses: actions/upload-artifact@v3 + with: + name: shell-lint-report + path: Shell_Script_Lint_Report.txt + + - name: Clean Up Containers + run: | + docker-compose down + + build-firmware: + name: Build Firmware + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Install Docker Compose + run: | + sudo apt-get update + sudo apt-get install -y docker-compose + + - name: Build and Start Docker Compose + run: | + docker-compose up -d --build + + - name: Build Firmware + run: | + docker-compose exec -T app bash -c "cd /workspace/build && cmake ../Software/Firmware/ && make -j$(nproc)" + + - name: Copy Firmware Files to Host + run: | + docker cp app:/workspace/build/IonizationChamber.cdb . + docker cp app:/workspace/build/IonizationChamber.lk . + docker cp app:/workspace/build/IonizationChamber.ihx . + docker cp app:/workspace/build/IonizationChamber.map . + + - name: Archive Firmware Build Artifacts + uses: actions/upload-artifact@v3 + with: + name: firmware-build-artifacts + path: | + IonizationChamber.cdb + IonizationChamber.lk + IonizationChamber.ihx + IonizationChamber.map + + - name: Clean Up Containers + run: | + docker-compose down diff --git a/.github/workflows/docs-generation.yml b/.github/workflows/docs-generation.yml deleted file mode 100644 index 540e0be..0000000 --- a/.github/workflows/docs-generation.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Docs Generation - -on: [push] - -jobs: - build_and_test: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: install latex and generate documents - run: | - sudo apt-get install -y texlive-latex-base texlive-latex-extra texlive-extra-utils poppler-utils pdf2svg - cd ./ContinuousIntegration - chmod +x ./run_generate_docs.sh - ./run_generate_docs.sh - mkdir result - cp ../Documentation/Diagrams/*.png ../Documentation/Diagrams/*.svg result - - - name: Archive latex docs - uses: actions/upload-artifact@v2 - if: always() - with: - name: Latex Documents - path: ./ContinuousIntegration/result \ No newline at end of file diff --git a/.github/workflows/static-code-analysis.yml b/.github/workflows/static-code-analysis.yml deleted file mode 100644 index eeca604..0000000 --- a/.github/workflows/static-code-analysis.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Static Code Analysis - -on: [push] - -jobs: - build_and_test: - - runs-on: ubuntu-latest - - steps: - - - uses: actions/checkout@v1 - - name: install cppcheck and run tests - run: | - sudo apt-get install -y cppcheck - cd ./ContinuousIntegration - chmod +x ./run_c_static_code_analysis.sh - ls run_c_static_code_analysis.sh - ./run_c_static_code_analysis.sh - - - uses: actions/checkout@v1 - - name: install flake8 and run tests - if: always() - run: | - sudo pip install flake8 flake8-html - cd ./ContinuousIntegration - chmod +x ./run_python_static_code_analysis.sh - ls - ./run_python_static_code_analysis.sh - - - uses: actions/checkout@v1 - - name: install shellcheck and run tests - if: always() - run: | - sudo apt-get install -y shellcheck - cd ./ContinuousIntegration - chmod +x ./run_shellscripts_static_code_analysis.sh - ls - ./run_shellscripts_static_code_analysis.sh - - - name: Archive Python results - uses: actions/upload-artifact@v2 - if: always() - with: - name: Report for Python sources - path: ./ContinuousIntegration/python_lint_report/ - - - name: Archive C results - uses: actions/upload-artifact@v2 - if: always() - with: - name: Report for C sources - path: ./ContinuousIntegration/C_Lint_*.txt - - - name: Archive shell scripts results - uses: actions/upload-artifact@v2 - if: always() - with: - name: Report for shell scripts sources - path: ./ContinuousIntegration/Shell_Script_Lint_Report.txt \ No newline at end of file diff --git a/.gitignore b/.gitignore deleted file mode 100644 index ba0430d..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -__pycache__/ \ No newline at end of file diff --git a/ContinuousIntegration/README.md b/ContinuousIntegration/README.md deleted file mode 100644 index 3503c1b..0000000 --- a/ContinuousIntegration/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# ContinuousIntegration - -This folder contains scripts run by GitHub continuous integration module. These scripts should be also run locally before pull request. diff --git a/ContinuousIntegration/run_generate_docs.sh b/ContinuousIntegration/run_generate_docs.sh deleted file mode 100644 index 34e3f0c..0000000 --- a/ContinuousIntegration/run_generate_docs.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -cd ../Documentation/Diagrams || return $? - -# generate .png from all .tex in current directory - -for filename_with_extension in *.tex -do - echo "processing $filename_with_extension..." - - # remove file exctension to made file handling easier - - filename=${filename_with_extension%.*} - - # convert .tex to .png - - pdflatex "$filename.tex" - touch "$filename-tmp.pdf" - pdfcrop "$filename.pdf" "$filename-tmp.pdf" - pdftoppm -png -r 800 "$filename-tmp.pdf" "$filename" - - - # convert .tex to .png - - pdf2svg "$filename-tmp.pdf" "$filename.svg" all -done - -rm ./*.aux ./*.log ./*.pdf diff --git a/ContinuousIntegration/run_python_static_code_analysis.sh b/ContinuousIntegration/run_python_static_code_analysis.sh deleted file mode 100644 index c369e02..0000000 --- a/ContinuousIntegration/run_python_static_code_analysis.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -flake8 --format=html --htmldir=python_lint_report ../Software/DataAcquisition/ ../Simulation \ No newline at end of file diff --git a/ContinuousIntegration/run_shellscripts_static_code_analysis.sh b/ContinuousIntegration/run_shellscripts_static_code_analysis.sh deleted file mode 100644 index cd65944..0000000 --- a/ContinuousIntegration/run_shellscripts_static_code_analysis.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -shellcheck ./*.sh | tee Shell_Script_Lint_Report.txt diff --git a/ContinuousIntegration/.gitignore b/DevOps/ContinuousIntegration/.gitignore similarity index 100% rename from ContinuousIntegration/.gitignore rename to DevOps/ContinuousIntegration/.gitignore diff --git a/DevOps/ContinuousIntegration/README.md b/DevOps/ContinuousIntegration/README.md new file mode 100644 index 0000000..647e58f --- /dev/null +++ b/DevOps/ContinuousIntegration/README.md @@ -0,0 +1,3 @@ +# ContinuousIntegration + +This folder contains scripts used by GitHub Continuous Integration. It is recommended to run these scripts locally before submitting a pull request. diff --git a/Software/Firmware/doxygen.cfg b/DevOps/ContinuousIntegration/doxygen.cfg similarity index 100% rename from Software/Firmware/doxygen.cfg rename to DevOps/ContinuousIntegration/doxygen.cfg diff --git a/ContinuousIntegration/run_c_static_code_analysis.sh b/DevOps/ContinuousIntegration/run_c_static_code_analysis.sh similarity index 100% rename from ContinuousIntegration/run_c_static_code_analysis.sh rename to DevOps/ContinuousIntegration/run_c_static_code_analysis.sh diff --git a/DevOps/ContinuousIntegration/run_python_static_code_analysis.sh b/DevOps/ContinuousIntegration/run_python_static_code_analysis.sh new file mode 100644 index 0000000..b36979b --- /dev/null +++ b/DevOps/ContinuousIntegration/run_python_static_code_analysis.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +# shellcheck disable=SC1091 +source /workspace/venv/bin/activate + +flake8 --format=html --htmldir=python_lint_report /workspace/Software/MeasurementAcquisition/ /workspace/Simulation \ No newline at end of file diff --git a/DevOps/ContinuousIntegration/run_shellscripts_static_code_analysis.sh b/DevOps/ContinuousIntegration/run_shellscripts_static_code_analysis.sh new file mode 100644 index 0000000..e2c8a9b --- /dev/null +++ b/DevOps/ContinuousIntegration/run_shellscripts_static_code_analysis.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +shellcheck /workspace/ContinuousIntegration/*.sh | tee Shell_Script_Lint_Report.txt diff --git a/Software/Firmware/uncrustify.cfg b/DevOps/ContinuousIntegration/uncrustify.cfg similarity index 100% rename from Software/Firmware/uncrustify.cfg rename to DevOps/ContinuousIntegration/uncrustify.cfg diff --git a/DevOps/Docker/Dockerfile b/DevOps/Docker/Dockerfile new file mode 100644 index 0000000..674d5a4 --- /dev/null +++ b/DevOps/Docker/Dockerfile @@ -0,0 +1,69 @@ +# Use an official Ubuntu as a base image +FROM ubuntu:20.04 AS build + +# Set environment variables to prevent interaction during installation +ENV DEBIAN_FRONTEND=noninteractive + +# Install git, build tools, and dependencies +RUN apt-get update && apt-get install -y \ + git \ + build-essential \ + cmake \ + pkg-config \ + libusb-1.0-0-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install stm8flash +RUN git clone https://github.com/vdudouyt/stm8flash.git +RUN cd stm8flash && make -j$(nproc) + +# Use another Ubuntu image for runtime +FROM ubuntu:20.04 AS runtime + +# Set environment variables to prevent interaction during installation +ENV DEBIAN_FRONTEND=noninteractive + +# Install runtime dependencies +RUN apt-get update && apt-get install -y \ + libusb-1.0-0 \ + sdcc \ + build-essential \ + cmake \ + git \ + make \ + pkg-config \ + libusb-1.0-0-dev \ + screen \ + doxygen \ + uncrustify \ + python3-pip \ + poppler-utils \ + cppcheck \ + r-base-core \ + shellcheck \ + dos2unix \ + && rm -rf /var/lib/apt/lists/* + +RUN apt-get update && apt-get install -y \ + python3-venv \ + && rm -rf /var/lib/apt/lists/* + +# Copy the stm8flash binary from the build stage +COPY --from=build /stm8flash/stm8flash /usr/bin/ + +# Install flake8 in a Python virtual environment +RUN python3 -m venv /workspace/venv && \ + /workspace/venv/bin/pip install --upgrade pip && \ + /workspace/venv/bin/pip install flake8 flake8-html pyserial + +# Install R libraries +RUN R -e "install.packages('latticeExtra', repos='http://cran.rstudio.com/')" +RUN R -e "install.packages('gridExtra', repos='http://cran.rstudio.com/')" +RUN R -e "install.packages('Hmisc', repos='http://cran.rstudio.com/')" + +# Create workspace directory and set it as the working directory +RUN mkdir -p /workspace/build +WORKDIR /workspace/build + +# Command to run the container +CMD ["bash"] diff --git a/DevOps/Docker/README.md b/DevOps/Docker/README.md new file mode 100644 index 0000000..061f3ba --- /dev/null +++ b/DevOps/Docker/README.md @@ -0,0 +1,88 @@ +# Docker + +# Purpose + +For me, using Docker in embedded systems has a key advantage: it eliminates the need for a README filled with outdated commands for setting up the development environment. In reality, such lists are rarely kept up to date (I often forget to update them myself too!). Docker solves this problem by providing a structured list of everything you need to install to get your environment up and running. But it's more than just a list - it's code, meaning it can be verified, maintained, and reused easily. + +# Prerequisites + +Install Docker. For Linux it should be simple, for Windows you need WSL installed first and some Linux image for it. +Build Docker image + +# Building, running, and stopping a Docker image + +In this step, we will build the Docker image and log into it. Once inside, we can launch the compilation, gather data from the device, run tools like linters, and more. + +Build the Docker Image. Navigate to the main directory (IonizationChamber) and run the following command to build the image. +This step is typically done only once and needs to be repeated after any modifications to the Dockerfile or docker-compose.yml: + +docker-compose build + +Start the Docker Image. Run the following command to start the Docker container: + +docker-compose up -d + +Log into the Docker Image: + +docker-compose exec app bash + +End of Work + +To log out from the Docker container, press Ctrl+D. +To stop and clean up the Docker environment, use: + +docker-compose down --remove-orphans + +# Building firmware + +Log into the Docker container (Building, running, and stopping a Docker image" section). + +Run the following commands: + +cmake ../Software/Firmware/ +make -j$(nproc) + +The produced binary is IonizationChamber.ihx. + +# Hardware flashing + +Log into the Docker container (Building, running, and stopping a Docker image" section). + +The stm8flash tool enumerates as a USB device. To allow non-root users to access this device (making it possible to flash the chip without root permissions), run the following command: + +chmod o+w /dev/bus/usb/001/004 + +In the example above, /dev/bus/usb/001/004 is the location where stm8flash enumerates. You can identify the correct ID for your stm8flash device from the error message received when attempting to flash the board. + +To flash the firmware to the board, use the following command: + +stm8flash -c stlink -p stm8s003f3 -w IonizationChamber.ihx + +## Running MeasurementAcquisition scripts + +Log into the Docker container (Building, running, and stopping a Docker image" section). + +Edit config.py to select the correct COM port for the Ionization Chamber. + +Run the data acquisition script. It will log the Ionization Chamber's output to the screen and save it to data.csv for further processing. + +python main.py + +## Running Simulation + +Log into the Docker container and navigate to the simulation directory: + +cd /workspace/Simulation/ + +Run the following command: + +python3 main.py + +Press Ctrl+C after a few seconds. + +The generated .csv file will be located at: + +/workspace/Simulation/data.csv + +# Credits: +* [stm8flash in Docker](https://github.com/ivankomolin/docker-stm8/blob/master/Dockerfile) \ No newline at end of file diff --git a/Documentation/Diagrams/MeasurementSequenceDiagram.plantuml b/Documentation/Diagrams/MeasurementSequenceDiagram.plantuml new file mode 100644 index 0000000..819986e --- /dev/null +++ b/Documentation/Diagrams/MeasurementSequenceDiagram.plantuml @@ -0,0 +1,31 @@ +@startuml +box "Layers" + participant "State Machine" + participant "Application Layer" + participant "Transport Layer" + participant "Physical Layer" + participant "Measurement Storage" +end box + +"State Machine" -> "Application Layer" : connect() +"Application Layer" -> "Transport Layer" : connect() +"Transport Layer" -> "Physical Layer" : connect() +"Physical Layer" -> "Device" : Establish connection + +loop Repeat for each measurement + +"State Machine" -> "Application Layer" : getMeasurement() +"Application Layer" -> "Transport Layer" : getFrame() +"Transport Layer" -> "Physical Layer" : getData() +"Device" -> "Physical Layer" : data +"Physical Layer" -> "Transport Layer" : data + +"Transport Layer" -> "Application Layer" : frame +"Application Layer" -> "State Machine" : measurement + +"State Machine" -> "Measurement Storage" : saveMeasurement() +"Measurement Storage" -> File : Write data to CSV + +"State Machine" -> Console : Display measurement +end +@enduml \ No newline at end of file diff --git a/Documentation/Diagrams/MeasurementSequenceDiagram.svg b/Documentation/Diagrams/MeasurementSequenceDiagram.svg new file mode 100644 index 0000000..c794201 --- /dev/null +++ b/Documentation/Diagrams/MeasurementSequenceDiagram.svg @@ -0,0 +1 @@ +LayersState MachineState MachineApplication LayerApplication LayerTransport LayerTransport LayerPhysical LayerPhysical LayerMeasurement StorageMeasurement StorageDeviceDeviceFileFileConsoleConsoleconnect()connect()connect()Establish connectionloop[Repeat for each measurement]getMeasurement()getFrame()getData()datadataframemeasurementsaveMeasurement()Write data to CSVDisplay measurement \ No newline at end of file diff --git a/Documentation/Diagrams/MeasurementStateMachine.plantuml b/Documentation/Diagrams/MeasurementStateMachine.plantuml new file mode 100644 index 0000000..ce66889 --- /dev/null +++ b/Documentation/Diagrams/MeasurementStateMachine.plantuml @@ -0,0 +1,31 @@ +@startuml +state "Ionization Chamber State Machine" as SM { + [*] --> InitIonizationChamber : Start + + state "Init Ionization Chamber" as InitIonizationChamber { + } + InitIonizationChamber --> InitMeasurementStorage : Connected + + state "Init Measurement Storage" as InitMeasurementStorage { + } + InitMeasurementStorage --> GetMeasurementFromIonizationChamber : Storage Ready + + state "Get Measurement From Ionization Chamber" as GetMeasurementFromIonizationChamber { + } + GetMeasurementFromIonizationChamber --> SaveMeasurement : Measurement Acquired + + state "Save Measurement" as SaveMeasurement { + } + SaveMeasurement --> ShowMeasurementToUser : Saved + + state "Show Measurement To User" as ShowMeasurementToUser { + } + ShowMeasurementToUser --> GetMeasurementFromIonizationChamber : Continue Measurement + + InitIonizationChamber --> [*] : Failure + InitMeasurementStorage --> [*] : Failure + GetMeasurementFromIonizationChamber --> [*] : Failure + SaveMeasurement --> [*] : Failure + ShowMeasurementToUser --> [*] : Failure +} +@enduml diff --git a/Documentation/Diagrams/MeasurementStateMachine.svg b/Documentation/Diagrams/MeasurementStateMachine.svg new file mode 100644 index 0000000..8872c3d --- /dev/null +++ b/Documentation/Diagrams/MeasurementStateMachine.svg @@ -0,0 +1 @@ +Ionization Chamber State MachineInit Ionization ChamberInit Measurement StorageGet Measurement From Ionization ChamberSave MeasurementShow Measurement To UserStartConnectedStorage ReadyMeasurement AcquiredSavedContinue MeasurementFailureFailureFailureFailureFailure \ No newline at end of file diff --git a/README.md b/README.md index 293fba2..4ccf6dc 100755 --- a/README.md +++ b/README.md @@ -1,12 +1,24 @@ -# Ionization Chamber (a device to measure radioactivity level) +# Ionization Chamber (a device for measuring radioactivity levels) -[![Build Firmware](https://github.com/RobertGawron/IonizationChamber/workflows/Build%20Firmware/badge.svg)](https://github.com/RobertGawron/IonizationChamber/actions?query=workflow%3A%22Build+Firmware%22) [![Static Code Analysis](https://github.com/RobertGawron/IonizationChamber/workflows/Static%20Code%20Analysis/badge.svg)](https://github.com/RobertGawron/IonizationChamber/actions?query=workflow%3A%22Static+Code+Analysis%22) +[![CI Pipeline](https://github.com/RobertGawron/IonizationChamber/actions/workflows/ci.yml/badge.svg)](https://github.com/RobertGawron/IonizationChamber/actions/workflows/ci.yml) + +## Objective + +There are many ionization chamber projects online, but most (though not all) produce false positive results. It's cool when a radioactive sample is placed near the detector and the detector shows an increased radiation value, but then, if you place your hand or any non-radioactive object nearby, the readings are high too. This is because, due to high amplification, these devices pick up a lot of noise, making the measurements unreliable. + +This project aims to address and eliminate this issue. ## Principle of operation -When air's atoms are hit by radioactive particles, an ion-pair is produced. Ions has electric charge, if they are in electric field create by positive and negative electrodes, negative ions will move to positive electrode and positive will move to negative electrode. +An ionization chamber is a type of radiation detector that measures ionizing radiation by detecting the charged particles (ions) produced when radiation interacts with the gas inside the chamber. The basic working principle relies on the ionization process. + +* **Radiation Interaction:** When ionizing radiation (such as alpha, beta, or gamma radiation) enters the chamber, it interacts with the gas inside, typically air. This interaction causes the gas molecules to become ionized, producing free electrons and positive ions. +* **Electric Field:** The chamber contains two electrodes: a central anode and a surrounding cathode. A high voltage is applied between these electrodes, creating an electric field inside the chamber. +* **Ion Collection:** The free electrons, which are negatively charged, are attracted to the positive anode, while the positively charged ions are attracted to the cathode. As these ions move toward the electrodes, they create an electrical current. +* **Current Measurement:** The generated current is directly proportional to the number of ions produced, which in turn is related to the amount of radiation that has passed through the chamber. This current is then measured and used to calculate the intensity of the radiation. + +Below is an image of the device that was assembled and tested (hardware revision 4.0). Since then, a new version has been developed but has not yet been tested. This repository, in its current state, represents the latest version. For details on the tested version, [refer to 4.0 tag](https://github.com/RobertGawron/IonizationChamber/releases/tag/4.0). -They will try to "meet each other" (I don't know how to explain it) thus creating a current. This current can be measured. The current is proportional to amount of ion-pairs. Amount of ion-pairs is proportional to radioactivity level. ![picture of device](https://raw.githubusercontent.com/RobertGawron/IonizationChamber/master/Documentation/Pictures/pcb_01_09_2019.jpg) @@ -18,26 +30,34 @@ It is designed in a way that the device can work remotely, e.g. no connection vi Remarks: -* Amplifier has three stages (first stage is transimpedance amplifier, not FET like most projects use). -* Amplifier has a separate symmetric power supply from 2x2V6 lithium batteries - +* The amplifier has three stages (the first stage is a transimpedance amplifier, not a FET transistor like most projects use). +* The ionization chamber is polarized with three 12V batteries connected in series. ## Hardware PCB was done in KiCAD. +### Hazards + +* **The battery container electrodes for chamber polarization are very close to the metal casing; the soldered electrodes should be filed down and secured with insulating tape to prevent short circuits.** +* **The device uses relatively high voltage (32V) to polarize the ionization chamber.** The electrodes of the ionization chamber should not be touched. ## Software -* ["Data processing and firmware flashing" node architecture -](https://github.com/RobertGawron/IonizationChamber/wiki/%22Data-processing-and-firmware-flashing%22-node-architecture -) -* [Setting up development environment on Linux -](https://github.com/RobertGawron/IonizationChamber/wiki/Setting-up-development-environment-on-Linux) -* [Firmware compilation and hardware flashing -](https://github.com/RobertGawron/IonizationChamber/wiki/Firmware-compilation-and-hardware-flashing) +* [Details about the firmware are available here.](./Software/Firmware/README.md) +* [Details about the acquisition software are available here.](./Software/MeasurementAcquisition/README.md) +* [Details about the measurement processing software are available here.](./Software/MeasurementAnalysis/README.md) + +In the future, data from the device will be gathered and processed using the [HardwareDataLogger project](https://github.com/RobertGawron/HardwareDataLogger), which is currently in development. + +## Simulation + +A simple mockup was created to generate dummy test data without the need for the real device. This allows testing of the acquisition software (mainly the scripts that generate output diagrams) without requiring hardware. + +[More details.](Simulation/README.md) + +## DevOps -## Hazards +All software is developed inside a Docker container. -* **The device exposes high voltage to user, although maximum current is very limited, it still poses health risk if the sensor external electrode would be touch.** -* **Pins of switch to turn on/off amplifier power supply are very close to metal chassis. It’s possible that pins will be shorted-out by chassis, shorting-out lithium batteries resulting in fire.** I flied off this part of chassis and used insulation tape to avoid it. +[More information about setting up the environment.](./DevOps/Docker/README.md) \ No newline at end of file diff --git a/Simulation/.gitignore b/Simulation/.gitignore index ca8bbeb..6f986c3 100644 --- a/Simulation/.gitignore +++ b/Simulation/.gitignore @@ -1 +1,2 @@ -data.csv \ No newline at end of file +__pycache__ +*.csv \ No newline at end of file diff --git a/Simulation/README.md b/Simulation/README.md index e69de29..ad06844 100644 --- a/Simulation/README.md +++ b/Simulation/README.md @@ -0,0 +1,9 @@ +# Simulation + +## Purpose + +This simulation generates .csv data with random values. The purpose is to test processing scripts without requiring the actual device. It uses a real Python application but stubs the low-level Python module that communicates with the device. + +# Usage + +[Information on how to use this tool can be found in the "Building, running, and stopping a Docker image" and "Running Simulation" sections.](../DevOps/Docker/README.md) diff --git a/Simulation/main.py b/Simulation/main.py index 0e34d44..4b03fe6 100644 --- a/Simulation/main.py +++ b/Simulation/main.py @@ -1,5 +1,5 @@ import sys -sys.path.append('../Software/DataAcquisition') +sys.path.append('../Software/MeasurementAcquisition') from physical_layer import PhysicalLayer # noqa: E402 from state_machine import IonizationChamberStateMachine # noqa: E402 diff --git a/Software/DataAcquisition/.gitignore b/Software/DataAcquisition/.gitignore deleted file mode 100644 index ca8bbeb..0000000 --- a/Software/DataAcquisition/.gitignore +++ /dev/null @@ -1 +0,0 @@ -data.csv \ No newline at end of file diff --git a/Software/DataAcquisition/README.md b/Software/DataAcquisition/README.md deleted file mode 100644 index d65f63e..0000000 --- a/Software/DataAcquisition/README.md +++ /dev/null @@ -1,80 +0,0 @@ -## Setting up development environment on Linux - -1. Install tools via apt-get: - -```console -apt-get install screen git sdcc doxygen uncrustify libusb-1.0-0-dev python3-pip texlive-latex-base texlive-latex-extra texlive-extra-utils poppler-utils cmake cppcheck r-base-core shellcheck -``` - -3. Install python libraries. -```console -pip3 install pyserial -pip3 install flake8 flake8-html -``` - -4. Install R libraries, run R in command line: -```console -pi@raspberrypi:~/IonizationChamber/software/DataAcquisitionFromDevice $ R - -R version 3.5.2 (2018-12-20) -- "Eggshell Igloo" -Copyright (C) 2018 The R Foundation for Statistical Computing -Platform: arm-unknown-linux-gnueabihf (32-bit) -``` - -Type (write yes on next prompts): - -``` -install.packages('latticeExtra') -``` - -``` -install.packages('gridExtra') -``` - -``` -install.packages('Hmisc') -``` - - -## Collecting measurements - -1. **Edit config.py** to select the correct COM port of Ionization Chamber. - -2. **Run data acquisition script**, it will log Ionization Chamber output on the screen and also it will save it to data.csv for further processing. - -``` -python main.py -``` - -## Plotting signal value in domain time + plotting histogram - -This mode is useful to look on measurement changes over time. - -After collecting data run script to post-process it and generate diagrams: - -``` -Rscript main.R -``` - -A new .png image with timestamp in its name will be created in directory where script is. - -Below is example of such generated plot. - -![boxplot](https://raw.githubusercontent.com/RobertGawron/IonizationChamber/master/Documentation/Plots/time_domain_example.png) - - -## Plotting values from different measurements [(box plot)](https://en.wikipedia.org/wiki/Box_plot) - -1. Collect data from different samples as different .csv files. -2. Edit ```boxplot.R```, to match filenames of .cvs files and labels of measurements. -3. Run: - -``` -Rscript boxplot.R -``` - -A new .png image with timestamp in its name will be created in directory where script is. - -Below is example of such generated plot. - -![boxplot](https://raw.githubusercontent.com/RobertGawron/IonizationChamber/master/Documentation/Plots/box_plot_example.png) diff --git a/Software/Firmware/.gitignore b/Software/Firmware/.gitignore deleted file mode 100644 index 567609b..0000000 --- a/Software/Firmware/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build/ diff --git a/Software/Firmware/README.md b/Software/Firmware/README.md index 0198b90..d69683b 100644 --- a/Software/Firmware/README.md +++ b/Software/Firmware/README.md @@ -1,60 +1,42 @@ -# Setting up development environment on Linux +# Architecture -1. Install tools via apt-get: +Measurements are collected from the COM port (tunneled over USB) by a Python script and stored in a .csv file. This file can later be parsed using R scripts to generate various diagrams, such as radioactivity changes over time, radioactivity histograms, and box plots for different samples. -```console -apt-get install screen git sdcc doxygen uncrustify libusb-1.0-0-dev python3-pip texlive-latex-base texlive-latex-extra texlive-extra-utils poppler-utils cmake cppcheck r-base-core shellcheck pdf2svg -``` -Note: libusb is needed by stm8flash. + -2. Clone, build and install stm8flash: +# Building Firmware -```console -git clone https://github.com/vdudouyt/stm8flash.git -cd stm8flash/ -make -make install -``` +Docker is used to create an isolated and reproducible work environment. -3. Stm8flash enumerates as USB device, add access to this device for non-root users (so that its possible to flash the chip without being root): +[Detailed information about setting up the environment.](../../DevOps/Docker/README.md) -```console -chmod o+w /dev/bus/usb/001/004 -``` +# Protocol for sending measurements via UART -In above example, _/dev/bus/usb/001/004_ is where the stm8flash enumerates, you will get id of your stm8flash from error message when trying to flash the board. +## Purpose -# Firmware compilation and hardware flashing +To ensure data integrity when sending information from the ionization chamber device to the computer, a simple protocol was added to encapsulate each data or command transmission. -## Initial configuration +## Protocol details -Configure project using cmake, this step is needed only once. +### Definition of the message -In Software directory create build directory and go into it: + -``` -mkdir build -cd build -``` +The field “msg length” describes the number of bytes in the “data” section. -Run cmake: +The content of the data section in the above message is an example and may vary depending on the message ID. Currently, only one message is supported, as shown above. -``` -cmake -DCMAKE_SYSTEM_NAME=Generic -DCMAKE_C_COMPILER=sdcc ../ -``` +### Defined message ids and message content -## Compilation +Currently, only one message type is defined (with ID = 1). -Compilation is done using make in the directory where cmake files were generated (Software/Build) +* Msg ID: 1 - Data from the last analog measurement of the actual value. +Msg Data Section: + * ADC configuration + * MSB (most significant byte) from ADC + * LSB (least significant byte) from ADC -``` -make -``` +### CRC -Binary will be stored directory where makefile is. +The CRC is calculated by XOR-ing all bytes in the "preamble" and "data" sections. -# Hardware flashing - -``` -stm8flash -c stlink -p stm8s003f3 -w IonizationChamber.ihx -``` diff --git a/Software/MeasurementAcquisition/.gitignore b/Software/MeasurementAcquisition/.gitignore new file mode 100644 index 0000000..6f986c3 --- /dev/null +++ b/Software/MeasurementAcquisition/.gitignore @@ -0,0 +1,2 @@ +__pycache__ +*.csv \ No newline at end of file diff --git a/Software/MeasurementAcquisition/README.md b/Software/MeasurementAcquisition/README.md new file mode 100644 index 0000000..071e0f9 --- /dev/null +++ b/Software/MeasurementAcquisition/README.md @@ -0,0 +1,27 @@ +# Simulation + +## Purpose + +This application gathers data from the device via UART over USB and stores timestamped measurements in a .csv file for further processing. + +It was developed to run on a Raspberry Pi but should work on any Linux or Windows system. One note for running it on Windows is that the name of the COM port (configured in myDeviceId) has a different format. + +# Usage + +[Information on how to use this tool can be found in the "Building, running, and stopping a Docker image" and "Running MeasurementAcquisition scripts" sections.](../DevOps/Docker/README.md) + + +## Architecture + +The diagram below shows the **Sequence Diagram** of this application: + +![state diagram](../../Documentation/Diagrams/MeasurementSequenceDiagram.svg) + +Note that the application can't be stopped normally; use Ctrl+C to terminate it. + +The diagram below shows the **State Diagram** of this application: + +![state diagram](../../Documentation/Diagrams/MeasurementStateMachine.svg) + +Note that the "Failure" state is not implemented. We assume that everything works correctly all the time. + diff --git a/Software/DataAcquisition/application_layer.py b/Software/MeasurementAcquisition/application_layer.py similarity index 100% rename from Software/DataAcquisition/application_layer.py rename to Software/MeasurementAcquisition/application_layer.py diff --git a/Software/DataAcquisition/config.py b/Software/MeasurementAcquisition/config.py similarity index 100% rename from Software/DataAcquisition/config.py rename to Software/MeasurementAcquisition/config.py diff --git a/Software/DataAcquisition/main.py b/Software/MeasurementAcquisition/main.py similarity index 100% rename from Software/DataAcquisition/main.py rename to Software/MeasurementAcquisition/main.py diff --git a/Software/DataAcquisition/measurement_storage.py b/Software/MeasurementAcquisition/measurement_storage.py similarity index 100% rename from Software/DataAcquisition/measurement_storage.py rename to Software/MeasurementAcquisition/measurement_storage.py diff --git a/Software/DataAcquisition/physical_layer.py b/Software/MeasurementAcquisition/physical_layer.py similarity index 100% rename from Software/DataAcquisition/physical_layer.py rename to Software/MeasurementAcquisition/physical_layer.py diff --git a/Software/DataAcquisition/state_machine.py b/Software/MeasurementAcquisition/state_machine.py similarity index 100% rename from Software/DataAcquisition/state_machine.py rename to Software/MeasurementAcquisition/state_machine.py diff --git a/Software/DataAcquisition/transport_layer.py b/Software/MeasurementAcquisition/transport_layer.py similarity index 100% rename from Software/DataAcquisition/transport_layer.py rename to Software/MeasurementAcquisition/transport_layer.py diff --git a/Software/MeasurementAnalysis/README.md b/Software/MeasurementAnalysis/README.md new file mode 100644 index 0000000..6c21a75 --- /dev/null +++ b/Software/MeasurementAnalysis/README.md @@ -0,0 +1,34 @@ +# Purpose + +This is a set of scripts that take .csv files and generate diagrams for easy analysis of measurements. + +# Plotting Signal Value in Time Domain + Plotting Histogram + +This mode is useful for observing measurement changes over time. + +After collecting data, run the script to post-process it and generate diagrams: + +Rscript main.R + +A new .png image with a timestamp in its name will be created in the directory where the script is located. + +Below is an example of such a generated plot. + +![boxplot](https://raw.githubusercontent.com/RobertGawron/IonizationChamber/master/Documentation/Plots/time_domain_example.png) + + +# Plotting Values from Different Measurements [(box plot)](https://en.wikipedia.org/wiki/Box_plot) + +Collect data from different samples as separate .csv files. + +Edit boxplot.R to match the filenames of the .csv files and the labels of the measurements. + +Run: + +Rscript boxplot.R + +A new .png image with a timestamp in its name will be created in the directory where the script is located. + +Below is an example of such a generated plot. + +![boxplot](https://raw.githubusercontent.com/RobertGawron/IonizationChamber/master/Documentation/Plots/box_plot_example.png) diff --git a/Software/DataAcquisition/boxplot.R b/Software/MeasurementAnalysis/boxplot.R similarity index 100% rename from Software/DataAcquisition/boxplot.R rename to Software/MeasurementAnalysis/boxplot.R diff --git a/Software/DataAcquisition/drawDiagramSingle.R b/Software/MeasurementAnalysis/drawDiagramSingle.R similarity index 100% rename from Software/DataAcquisition/drawDiagramSingle.R rename to Software/MeasurementAnalysis/drawDiagramSingle.R diff --git a/Software/DataAcquisition/main.R b/Software/MeasurementAnalysis/main.R similarity index 100% rename from Software/DataAcquisition/main.R rename to Software/MeasurementAnalysis/main.R diff --git a/Software/README.md b/Software/README.md deleted file mode 100644 index 384d359..0000000 --- a/Software/README.md +++ /dev/null @@ -1,34 +0,0 @@ -## Architecture - -Measurements are collected from COM port (tunneled over USB) by a python script and stored in .cvs file. This file can be later parsed using R scripts to to collect various diagrams (radioactivity changes over time, radioactivity histogram, box-plots for various samples). - - - - -## Protocol for sending measurements via UART - -## Purpose - -To ensure data integrity sent from the ionization chamber device to computer, a simple protocol was added to encapsulate each data/command send. - -## Protocol details - -The field “msg length” describes amount of bytes the “data” section has. - -Definition of the message: - - - -Content of data section in above message is an example and can be different depends on message id, but now only one message is supported and it is as shown above. - - -### Defined message ids and message content - -* Msg id: 1 - data from last analog measurement of actual value. -* Msg data section: -* ADC configuration -* MSB (most significant byte) from ADC -* LSB (least significant byte) from ADC - -### CRC -CRC is calculated xor’ing all bytes in "preamble" and "data" section. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..51f3e11 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +services: + app: + container_name: app + build: + context: ./DevOps/Docker + image: chamber:latest + working_dir: /workspace/build + stdin_open: true # Keep stdin open for interaction + tty: true # Allocate a TTY for interactive Bash + volumes: + - ./Simulation:/workspace/Simulation + - ./Software:/workspace/Software + - ./DevOps/ContinuousIntegration:/workspace/ContinuousIntegration