inverter

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit bc348e535b5ad89e70920e487d59da0742038a39
Author: Petar Yotsev <petar@yotsev.xyz>
Date:   Mon, 12 Jul 2021 02:35:45 +0100

Initial commit

Diffstat:
AMakefile | 22++++++++++++++++++++++
AREADME.md | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Ainverter.ino | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 191 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,22 @@ +BOARDS_TXT = /usr/share/arduino/hardware/archlinux-arduino/avr/boards.txt +ARDUINO_DIR = /usr/share/arduino +ARDMK_DIR = /usr/share/arduino + +# ARDUINO_LIBS = +# USER_LIB_PATH = ./lib + +ARDMK_VENDOR = arduino +BOARD_TAG = nano +BOARD_SUB = atmega328 +ARCHITECTURE = avr +AVRDUDE_ARD_BAUDRATE = 57600 +MONITOR_PORT = /dev/ttyUSB* + +AVR_TOOLS_DIR = /usr +AVRDUDE_CONF = /etc/avrdude.conf +ARDUINO_CORE_PATH = /usr/share/arduino/hardware/archlinux-arduino/avr/cores/arduino +ARDUINO_PLATFORM_LIB_PATH = /usr/share/arduino/hardware/archlinux-arduino/avr/libraries +ARDUINO_VAR_PATH = /usr/share/arduino/hardware/archlinux-arduino/avr/variants +BOOTLOADER_PARENT = /usr/share/arduino/hardware/archlinux-arduino/avr/bootloaders + +include /usr/share/arduino/Arduino.mk diff --git a/README.md b/README.md @@ -0,0 +1,50 @@ +## About + +This is a program for the Arduino Nano that generates control signals +with power width modulation (pwm) for a simple inverter circuit. + +## Installation + +Connect an Arduino nano with a USB cable and run + + make upload + +from the project directory. + +The project was created on Arch Linux with `Arduino.mk`. If you run it +under a different operating system, you should change the paths in the +Makefile. It uses half the baude rate because the nano I'm using has an +older bootloader. + +## Usage + +The builtin LED will flash while the board is calculating the time +intervals of the pwm for the specified frequency. + +Here's a diagram of the circuit: + + ____________ + | | | + | p1 n1 + + | | + bat |--load--| + - | | + | p2 n2 + |___|________| + +I didn't have four transistors of the same type. + +## Specifics + +The code uses floats because on ATMEGA based boards doubles are the +same as floats. I wanted to make that explicit. If your board supports +doubles, you can change the base case in Converge() to get more +accuracy. The limited accuracy of floats also restricts the resolution +or how many distinct intervals can be calculated in a cycle. The higher +the resolution, the smoother the modulation becomes. The default +resolution is 220 roots in a cycles (219 intervals) and the maximum +resolution that doesn't brake everything (on my nano) is 227. + +## License + +GPLv2 diff --git a/inverter.ino b/inverter.ino @@ -0,0 +1,119 @@ +#include <math.h> + +#define p1 7 +#define p2 6 +#define n1 5 +#define n2 4 + +/* specify the frequency of AC */ +/* =========================== */ +constexpr float freq = 10.0f; +/* =========================== */ + +// resolution / number of roots +constexpr int res = 220; + +// temporary pointer for the top of an array +unsigned int index = 0; +float roots[res]; +int time_intervals[res - 1]; // in microseconds + +constexpr float pi = 3.141592653589793; + +float Wave(const float& x) +{ + return (2.1f / pi) * asin(sin(float(res) * pi * x)) + + sin(2.0f * pi * x - pi / 2.0f); +} + +bool led_is_on = false; + +void Converge( + const float& lower, + const float& upper, + const int& exponent) +{ + // base case, maximum float precision reached for root + if (exponent < -7) { + roots[index] = (lower + upper) / 2; + index++; + // flash builtin LED + digitalWrite(LED_BUILTIN, (led_is_on) ? LOW : HIGH); + led_is_on = !led_is_on; + return; + } + + // record if the wave function is positive or negative before it + // crosses the x-axis + bool is_positive = (Wave(lower) > 0) ? true : false; + // define the incremental step + float step = 1.0f * pow(10, exponent); + + // scan for a change of sign in Wave() between upper and lower bound + for (float func, x = lower; x < upper + step; x += step) { + // record output of Wave() to avoid multiple calls for same x + func = Wave(x); + // sign of the output has changed / root is found + if ((func > 0 && !is_positive) || (func < 0 && is_positive)) { + // go one magnitude lower for more precision + Converge(x - step, x, exponent - 1); + is_positive = !is_positive; + } + } +} + +void setup() +{ + pinMode(p1, OUTPUT); + pinMode(p2, OUTPUT); + pinMode(n1, OUTPUT); + pinMode(n2, OUTPUT); + + pinMode(LED_BUILTIN, OUTPUT); + + // find roots + Converge(0, 1, -4); + + digitalWrite(LED_BUILTIN, LOW); + + // calculate intervals between roots + index = 0; + for (int i = 1; i < res; ++i) { + time_intervals[index] + = int(1000000.0f * (roots[i] - roots[i - 1]) / (freq * 2.0f)); + index++; + } +} + +void loop() +{ + // set other set of transistors off to avoid feedback + digitalWrite(p2, LOW); + digitalWrite(n1, HIGH); + // set first transistor (from +) on + digitalWrite(p1, HIGH); + + for (int i = 0; i < res - 1; i += 2) { + // set second transistor (from +) on + digitalWrite(n2, LOW); + delayMicroseconds(time_intervals[i]); + // set second transistor (from +) off + digitalWrite(n2, HIGH); + delayMicroseconds(time_intervals[i + 1]); + } + + // set other set of transistors off to avoid feedback + digitalWrite(p1, LOW); + digitalWrite(n2, HIGH); + // set first transistor (from +) on + digitalWrite(p2, HIGH); + + for (int i = 0; i < res - 1; i += 2) { + // set second transistor (from +) on + digitalWrite(n1, LOW); + delayMicroseconds(time_intervals[i]); + // set second transistor (from +) off + digitalWrite(n1, HIGH); + delayMicroseconds(time_intervals[i + 1]); + } +}