This commit is contained in:
137
content/snippets/0020-debouncing.md
Normal file
137
content/snippets/0020-debouncing.md
Normal file
@ -0,0 +1,137 @@
|
||||
<!--
|
||||
title: Yet Another Debouncing Method
|
||||
date: 2018-04-30
|
||||
-->
|
||||
|
||||
You can find several approaches for debouncing mechanical switches on the Internet, some work better, some not so good.
|
||||
|
||||
One common approach is to ignore events in an ISR when they come too fast:<
|
||||
|
||||
```
|
||||
void count() {
|
||||
static uint32_t lastEvent = 0;
|
||||
uint32_t currentEvent = micros();
|
||||
if (currentEvent > (lastEvent + configBlock.debounce)) {
|
||||
lastEvent = currentEvent;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(REED_PIN, INPUT_PULLUP);
|
||||
attachInterrupt(REED_PIN, count, FALLING);
|
||||
}
|
||||
```
|
||||
|
||||
This works very good when only the tipping of a switch is relevant.
|
||||
|
||||
When also the time the button was pressed is relevant and when it is especially necessary to distinguish between a short and a long press this approach doesn't work anymore.
|
||||
|
||||
Since I couldn't remember the approaches I read about earlier I've sketched this state machine:
|
||||
|
||||

|
||||
|
||||
(The double-lined states are action-states which send out the related information.)
|
||||
|
||||
At least for me, this approach is working very reliable so far, I'm quite happy with it.
|
||||
|
||||
```
|
||||
enum tPressedState { psHIGH, psLOW, psACCEPTED_LOW, psLONG_START, psLONG_CONT, psLONG_CONT_SEND, psLONG_END, psSHORT, psINVALID };
|
||||
|
||||
typedef struct {
|
||||
uint8_t index;
|
||||
uint8_t buttonPin;
|
||||
tPressedState pressedState;
|
||||
tPressedState oldPressedState;
|
||||
uint32_t lastStateChange;
|
||||
} tButton;
|
||||
|
||||
tButton buttons[] = {
|
||||
{ 1, SWITCH_1, psHIGH, psINVALID, 0 },
|
||||
{ 2, SWITCH_2, psHIGH, psINVALID, 0 },
|
||||
{ 3, SWITCH_3, psHIGH, psINVALID, 0 },
|
||||
{ 0, 0, psINVALID, psINVALID, 0 } // END MARKER
|
||||
};
|
||||
|
||||
static void buttonHandler(tButton *button) {
|
||||
uint32_t currentMicros = micros();
|
||||
uint8_t buttonState = digitalRead(button->buttonPin);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (button->oldPressedState != button->pressedState) {
|
||||
Serial.print("Index ");
|
||||
Serial.print(button->index);
|
||||
Serial.print(", state changed from ");
|
||||
Serial.print(button->oldPressedState);
|
||||
Serial.print(" to ");
|
||||
Serial.print(button->pressedState);
|
||||
Serial.println();
|
||||
button->oldPressedState = button->pressedState;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (button->pressedState) {
|
||||
case psHIGH:
|
||||
if (buttonState == LOW) {
|
||||
button->pressedState = psLOW;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
break;
|
||||
case psLOW:
|
||||
if (buttonState == HIGH) {
|
||||
button->pressedState = psHIGH;
|
||||
button->lastStateChange = currentMicros;
|
||||
} else {
|
||||
if (currentMicros > (button->lastStateChange + configBlock.debounce)) {
|
||||
button->pressedState = psACCEPTED_LOW;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case psACCEPTED_LOW:
|
||||
if (buttonState == HIGH) {
|
||||
button->pressedState = psSHORT;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
if (currentMicros > (button->lastStateChange + (configBlock.longPress * 1000))) {
|
||||
button->pressedState = psLONG_START;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
break;
|
||||
case psSHORT:
|
||||
sendMsg(button->index, "PRESS_SHORT");
|
||||
button->pressedState = psHIGH;
|
||||
button->lastStateChange = currentMicros;
|
||||
break;
|
||||
case psLONG_START:
|
||||
sendMsg(button->index, "PRESS_LONG_START");
|
||||
button->pressedState = psLONG_CONT;
|
||||
button->lastStateChange = currentMicros;
|
||||
break;
|
||||
case psLONG_CONT:
|
||||
if (buttonState == HIGH) {
|
||||
button->pressedState = psLONG_END;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
if (currentMicros > (button->lastStateChange + (configBlock.longPressRepeat * 1000))) {
|
||||
button->pressedState = psLONG_CONT_SEND;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
break;
|
||||
case psLONG_CONT_SEND:
|
||||
sendMsg(button->index, "PRESS_LONG_CONT");
|
||||
button->pressedState = psLONG_CONT;
|
||||
button->lastStateChange = currentMicros;
|
||||
break;
|
||||
case psLONG_END:
|
||||
sendMsg(button->index, "PRESS_LONG_END");
|
||||
button->pressedState = psHIGH;
|
||||
button->lastStateChange = currentMicros;
|
||||
break;
|
||||
default:
|
||||
button->pressedState = psHIGH;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
8
content/snippets/0030-ca-certificates-in-debian.md
Normal file
8
content/snippets/0030-ca-certificates-in-debian.md
Normal file
@ -0,0 +1,8 @@
|
||||
<!--
|
||||
title: How to add a CA certificate in Debian
|
||||
-->
|
||||
|
||||
Copy CA file with extension `crt` into `/usr/local/share/ca-certificates/`.
|
||||
|
||||
Call `update-ca-certificates` as root.
|
||||
|
34
content/snippets/0040-colors-in-minicom.md
Normal file
34
content/snippets/0040-colors-in-minicom.md
Normal file
@ -0,0 +1,34 @@
|
||||
<!--
|
||||
title: Colors in Minicom
|
||||
-->
|
||||
|
||||
To start `minicom` in color mode use
|
||||
|
||||
```
|
||||
minicom -c on
|
||||
```
|
||||
|
||||
Switch terminal emulation to ANSI.
|
||||
|
||||
Use escape sequences to actually change the color of text as described for instance here
|
||||
|
||||
https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html.
|
||||
|
||||
The base sequence is `\1b[Xm` where X is a number as described below.
|
||||
|
||||
To get the colors in bright style, use the sequence `\x1b[X;1m`.
|
||||
|
||||
Number | Color
|
||||
----|----
|
||||
0 | reset
|
||||
1 | highlight
|
||||
7 | inverse
|
||||
30 | black
|
||||
31 | red
|
||||
32 | green
|
||||
33 | yellow
|
||||
34 | blue
|
||||
35 | magenta
|
||||
36 | cyan
|
||||
37 | white
|
||||
|
58
content/snippets/0050-email-childprot.md
Normal file
58
content/snippets/0050-email-childprot.md
Normal file
@ -0,0 +1,58 @@
|
||||
<!--
|
||||
title: Children Protection for Postfix-based EMail-Server
|
||||
date: 2013-06-27
|
||||
-->
|
||||
|
||||
This small tool implements a whitelist on a Postfix mail-server. It prevents certain recipient addresses (your kids ones) from
|
||||
receiving mail from any not whitelisted address. Any mail from not whitelisted senders is redirected to a delegate (a parent).
|
||||
|
||||
The code for this tool can is here: [https://gitea.hottis.de/wn/childprot](https://gitea.hottis.de/wn/childprot).
|
||||
|
||||
Configure the tool by adding this line into the `master.cf` of the Postfix installation:
|
||||
|
||||
```
|
||||
childprot unix - n n - 25 spawn user=mail argv=/opt/sbin/ChildProt
|
||||
```
|
||||
|
||||
and this one to the `main.cf`:
|
||||
|
||||
```
|
||||
check_policy_service unix:private/childprot
|
||||
```
|
||||
|
||||
The restricted recipients and the whitelists are stored in an SQLite3 database:
|
||||
|
||||
```
|
||||
CREATE TABLE child_address_t (
|
||||
child INTEGER REFERENCES child_t(id),
|
||||
address TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE child_t (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT,
|
||||
delegate TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE whitelist_t (
|
||||
child INTEGER REFERENCES child_t(id),
|
||||
address TEXT
|
||||
);
|
||||
|
||||
CREATE VIEW child_v AS
|
||||
SELECT c.id as id,
|
||||
c.delegate as delegate,
|
||||
ca.address as address
|
||||
FROM child_t c,
|
||||
child_address_t ca
|
||||
WHERE c.id = ca.child;
|
||||
```
|
||||
|
||||
Restricted persons together with their delegates are added to the table `child_t`, multiple addresses can be assigned to those persons in
|
||||
`child_address_t`. Whitelists per person are maintained in `whitelist_t`.
|
||||
|
||||
The tool is querying the view `child_v`.
|
||||
|
||||
**Note: The code is unmaintained and here only for documentary reasons. It is not meant to be used any longer.**
|
||||
|
||||
|
18
content/snippets/0060-engel-des-herrn.md
Normal file
18
content/snippets/0060-engel-des-herrn.md
Normal file
@ -0,0 +1,18 @@
|
||||
<!--
|
||||
title: Engel des Herrn
|
||||
-->
|
||||
|
||||
|
||||
Der Engel des Herrn brachte Maria die Botschaft, und sie empfing vom Heiligen Geist.
|
||||
Gegrüßet seist du, Maria …
|
||||
|
||||
Maria sprach: Siehe, ich bin die Magd des Herrn; mir geschehe nach deinem Wort.
|
||||
Gegrüßet seist du, Maria …
|
||||
|
||||
Und das Wort ist Fleisch geworden und hat unter uns gewohnt.
|
||||
Gegrüßet seist du, Maria …
|
||||
|
||||
Bitte für uns, heilige Gottesmutter (heilige Gottesgebärerin), (auf) dass wir würdig werden der Verheißungen Christi.
|
||||
|
||||
Lasset uns beten. Allmächtiger Gott, gieße deine Gnade in unsere Herzen ein. Durch die Botschaft des Engels haben wir die Menschwerdung Christi, deines Sohnes, erkannt. Führe uns durch sein Leiden und Kreuz zur Herrlichkeit der Auferstehung. Darum bitten wir durch Christus, unsern Herrn. Amen.
|
||||
|
61
content/snippets/0070-gitlab-backup.md
Normal file
61
content/snippets/0070-gitlab-backup.md
Normal file
@ -0,0 +1,61 @@
|
||||
<!--
|
||||
title: Gitlab Backup and Restore
|
||||
-->
|
||||
|
||||
## Backup
|
||||
Find the backup directory:
|
||||
```
|
||||
grep backup_path /etc/gitlab/gitlab.rb
|
||||
```
|
||||
|
||||
Issue backup:
|
||||
```
|
||||
sudo gitlab-backup create
|
||||
```
|
||||
|
||||
Transfer backup using scp to destination machine.
|
||||
|
||||
Backup configuration and secrets:
|
||||
```
|
||||
sudp cp /etc/gitlab/gitlab-secrets.json /backuppath/
|
||||
sudo cp /etc/gitlab/gitlab.rb /backuppath/
|
||||
```
|
||||
|
||||
## Restore
|
||||
|
||||
See also here: [https://docs.gitlab.com/ee/administration/backup_restore/restore_gitlab.html](https://docs.gitlab.com/ee/administration/backup_restore/restore_gitlab.html)
|
||||
|
||||
*DO NOT OVERWRITE THE CONFIGURATION ON THE DESTINATION MACHINE. COMPARE IT AND CONSIDER AND EVALUATE EACH DIFFERENCE*
|
||||
|
||||
Stop processes of GitLab connecting to the database:
|
||||
```
|
||||
gitlab-ctl stop puma
|
||||
gitlab-ctl stop sidekiq
|
||||
# check
|
||||
gitlab-ctl status
|
||||
```
|
||||
Do not stop the whole system since the restore tool has to connect to the database which would also stop in that case.
|
||||
|
||||
|
||||
|
||||
Issue restore. Run this command in a screen session. It is running quite long and requires manual intervention in between.
|
||||
|
||||
```
|
||||
sudo gitlab-backup restore BACKUP=...
|
||||
```
|
||||
Use the datecode and the version tag of the backup created above.
|
||||
|
||||
Remember secrets and configuration. Do not overwrite configuration, see above.
|
||||
|
||||
Reconfigure the instance:
|
||||
```
|
||||
sudo gitlab-ctl reconfigure
|
||||
```
|
||||
|
||||
Start the instance:
|
||||
```
|
||||
sudo gitlab-ctl start
|
||||
```
|
||||
|
||||
|
||||
|
27
content/snippets/0080-gitlab-change-baseurl.md
Normal file
27
content/snippets/0080-gitlab-change-baseurl.md
Normal file
@ -0,0 +1,27 @@
|
||||
<!--
|
||||
title: Gitlab Change BaseURL in Database
|
||||
-->
|
||||
|
||||
## Change URL
|
||||
|
||||
After a migration changing the base url in the configuration is not enough. It must also be changed in the database.
|
||||
|
||||
* Adjust the variable `external_url` in the file `/etc/gitlab/gitlab.rb` and run `gitlab-ctl reconfigure`
|
||||
* Adjust the canonical URL in the database:
|
||||
```
|
||||
gitlab-rails console
|
||||
ApplicationSetting.current.update!(home_page_url: 'https://neue-url.example.com')
|
||||
ApplicationSetting.current.update!(after_sign_out_path: 'https://neue-url.example.com')
|
||||
```
|
||||
* Reading out a value from the ApplicationSetting via the gitlab-rails console is done using
|
||||
```
|
||||
ApplicationSetting.current.home_page_url
|
||||
```
|
||||
* Clear the internal cache:
|
||||
```
|
||||
gitlab-rake cache:clear
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
24
content/snippets/0090-gitlab-upgrades.md
Normal file
24
content/snippets/0090-gitlab-upgrades.md
Normal file
@ -0,0 +1,24 @@
|
||||
<!--
|
||||
title: Gitlab Upgrades
|
||||
-->
|
||||
|
||||
## Upgrade of a GitLab instance
|
||||
|
||||
When upgrading a Gitlab instance, strictly follow the defined upgrade path. Consider to snapshot the filesystem if possible after each step.
|
||||
|
||||
Additional, after each step wait until all background migrations are completed before performing the next upgrade step.
|
||||
|
||||
|
||||
* [Upgrade Paths](https://docs.gitlab.com/ee/update/index.html#upgrade-paths)
|
||||
* [Upgrading to a specific version](https://docs.gitlab.com/ee/update/package/#upgrade-to-a-specific-version-using-the-official-repositories)
|
||||
|
||||
To find the versions of a specific package in the Debian apt cache use
|
||||
|
||||
```
|
||||
apt-cache madison gitlab-ce
|
||||
```
|
||||
To upgrade to a specific version use
|
||||
```
|
||||
apt install gitlab-ce=<version>
|
||||
```
|
||||
**Definitely observe the version specific upgrade instructions, especially background migrations!**
|
63
content/snippets/0100-iscsi-on-linux.md
Normal file
63
content/snippets/0100-iscsi-on-linux.md
Normal file
@ -0,0 +1,63 @@
|
||||
<!--
|
||||
title: iSCSI on Linux
|
||||
-->
|
||||
|
||||
## Preparation
|
||||
Install `open-iscsi`, at least on Debian systems.
|
||||
|
||||
|
||||
## Use an iSCSI target from Linux
|
||||
|
||||
In our setup a Synology NAS at 172.16.200.19 provides the targets.
|
||||
|
||||
First, run
|
||||
```
|
||||
iscsiadm -m discovery -t sendtargets -p 172.16.200.19
|
||||
```
|
||||
to discover all provided targets.
|
||||
|
||||
You get something like this
|
||||
```
|
||||
172.16.200.19:3260,1 iqn.2000-01.com.synology:nas.Target-GitLab.db1c0541e7
|
||||
[fe80::211:32ff:febe:da31]:3260,1 iqn.2000-01.com.synology:nas.Target-GitLab.db1c0541e7
|
||||
172.16.200.19:3260,1 iqn.2000-01.com.synology:nas.Target-Bitwarden.db1c0541e7
|
||||
[fe80::211:32ff:febe:da31]:3260,1 iqn.2000-01.com.synology:nas.Target-Bitwarden.db1c0541e7
|
||||
172.16.200.19:3260,1 iqn.2000-01.com.synology:nas.Target-Nextcloud.db1c0541e7
|
||||
[fe80::211:32ff:febe:da31]:3260,1 iqn.2000-01.com.synology:nas.Target-Nextcloud.db1c0541e7
|
||||
172.16.200.19:3260,1 iqn.2000-01.com.synology:nas.Target-MariaDB.db1c0541e7
|
||||
[fe80::211:32ff:febe:da31]:3260,1 iqn.2000-01.com.synology:nas.Target-MariaDB.db1c0541e7
|
||||
172.16.200.19:3260,1 iqn.2000-01.com.synology:nas.Target-Backup.db1c0541e7
|
||||
[fe80::211:32ff:febe:da31]:3260,1 iqn.2000-01.com.synology:nas.Target-Backup.db1c0541e7
|
||||
```
|
||||
|
||||
Now, connect to the target using
|
||||
```
|
||||
iscsiadm -m node --targetname "iqn.2000-01.com.synology:nas.Target-Backup.db1c0541e7" \
|
||||
--portal 172.16.200.19 --login
|
||||
```
|
||||
|
||||
A new SCSI device will be created. Check the name of the device using ''dmesg''. You see something like this
|
||||
```
|
||||
[16924536.979916] scsi host13: iSCSI Initiator over TCP/IP
|
||||
[16924537.010635] scsi 13:0:0:1: Direct-Access SYNOLOGY iSCSI Storage 4.0 PQ: 0 ANSI: 5
|
||||
[16924537.011449] sd 13:0:0:1: Attached scsi generic sg10 type 0
|
||||
[16924537.012597] sd 13:0:0:1: [sdj] 209715200 512-byte logical blocks: (107 GB/100 GiB)
|
||||
[16924537.012827] sd 13:0:0:1: [sdj] Write Protect is off
|
||||
[16924537.012828] sd 13:0:0:1: [sdj] Mode Sense: 43 00 10 08
|
||||
[16924537.013111] sd 13:0:0:1: [sdj] Write cache: enabled, read cache: enabled, supports DPO and FUA
|
||||
[16924537.013361] sd 13:0:0:1: [sdj] Optimal transfer size 16384 logical blocks > dev_max (8192 logical blocks)
|
||||
[16924537.018630] sd 13:0:0:1: [sdj] Attached SCSI disk
|
||||
```
|
||||
|
||||
Now use `fdisk`, `mkfs` and if you like `blkid` on the new device and put it into the `/etc/fstab`.
|
||||
|
||||
|
||||
===== Authenticated target =====
|
||||
|
||||
```
|
||||
iscsiadm --mode node --targetname "iqn.2007-01.org.debian.foobar:CDs" -p 192.168.0.1:3260 --op=update --name node.session.auth.authmethod --value=CHAP
|
||||
iscsiadm --mode node --targetname "iqn.2007-01.org.debian.foobar:CDs" -p 192.168.0.1:3260 --op=update --name node.session.auth.username --value=$Id
|
||||
iscsiadm --mode node --targetname "iqn.2007-01.org.debian.foobar:CDs" -p 192.168.0.1:3260 --op=update --name node.session.auth.password --value=$MDP
|
||||
iscsiadm --mode node --targetname "iqn.2007-01.org.debian.foobar:CDs" -p 192.168.0.1:3260 --login
|
||||
```
|
||||
|
44
content/snippets/0110-magnifikat.md
Normal file
44
content/snippets/0110-magnifikat.md
Normal file
@ -0,0 +1,44 @@
|
||||
<!--
|
||||
title: Magnifikat
|
||||
-->
|
||||
|
||||
|
||||
|
||||
Bibellese zum 15.12.2013
|
||||
|
||||
|
||||
|
||||
1,46 Und Maria sprach:
|
||||
Meine Seele erhebt den Herrn,
|
||||
|
||||
47 und mein Geist freut sich Gottes, meines Heilandes;
|
||||
|
||||
48 denn er hat die Niedrigkeit seiner Magd angesehen.
|
||||
Siehe, von nun an werden mich selig preisen alle Kindeskinder.
|
||||
|
||||
49 Denn er hat große Dinge an mir getan,
|
||||
der da mächtig ist und dessen Name heilig ist.
|
||||
|
||||
50 Und seine Barmherzigkeit währt von Geschlecht zu Geschlecht
|
||||
bei denen, die ihn fürchten.
|
||||
|
||||
51 Er übt Gewalt mit seinem Arm
|
||||
und zerstreut, die hoffärtig sind in ihres Herzens Sinn.
|
||||
|
||||
52 Er stößt die Gewaltigen vom Thron
|
||||
und erhebt die Niedrigen.
|
||||
|
||||
53 Die Hungrigen füllt er mit Gütern
|
||||
und lässt die Reichen leer ausgehen.
|
||||
|
||||
54 Er gedenkt der Barmherzigkeit
|
||||
und hilft seinem Diener Israel auf,
|
||||
|
||||
55 wie er geredet hat zu unsern Vätern,
|
||||
Abraham und seinen Kindern in Ewigkeit.
|
||||
|
||||
|
||||
Lukas 1,46-55
|
||||
|
||||
http://m.die-bibel.de/luther-bibel-1984/bibelstelle/Lukas%201?utm_source=Bibellese_Apple&utm_medium=App&utm_campaign=Bibellese
|
||||
|
37
content/snippets/0120-neovim.md
Normal file
37
content/snippets/0120-neovim.md
Normal file
@ -0,0 +1,37 @@
|
||||
<!--
|
||||
title: Neovim Setup
|
||||
-->
|
||||
|
||||
Lots of information on nvim can be found for instance here:
|
||||
|
||||
* https://programmingpercy.tech/blog/learn-how-to-use-neovim-as-ide/
|
||||
* https://github.com/hrsh7th/
|
||||
* https://github.com/wbthomason/packer.nvim
|
||||
* https://docs.rockylinux.org/books/nvchad/nvchad_ui/nvimtree/
|
||||
|
||||
## Installation of Neovim
|
||||
On Debian install neovim from the sources, the packages are mostly a bit aged.
|
||||
```shell
|
||||
git clone https://github.com/neovim/neovim
|
||||
sudo apt install ninja-build gettext cmake unzip curl
|
||||
make CMAKE_BUILD_TYPE=Release
|
||||
sudo make install
|
||||
```
|
||||
On Windows install from binary or using installer, on MacOS use `brew`.
|
||||
|
||||
Debian packages can be found here: https://github.com/neovim/neovim-releases/releases
|
||||
|
||||
|
||||
## Configuration
|
||||
Clone the packer repository:
|
||||
```shell
|
||||
git clone --depth 1 https://github.com/wbthomason/packer.nvim ~/.local/share/nvim/site/pack/packer/start/packer.nvim
|
||||
```
|
||||
Clone the local configuration repo:
|
||||
```shell
|
||||
git clone git@gitea.hottis.de:wn/my-nvim-config.git ~/.config/nvim
|
||||
```
|
||||
At the first start of nvim a lot of error messages will be shown. Ignore them and run `:PackerInstall`. At the next start everything should be fine.
|
||||
|
||||
The file `~/.config/nvim/init.lua` contains both plugins to be loaded and regular settings for nvim. The directory `~/.config/nvim/lua` contains configuration for individual plugins.
|
||||
|
19
content/snippets/0130-occ-in-nextcloud-pod.md
Normal file
19
content/snippets/0130-occ-in-nextcloud-pod.md
Normal file
@ -0,0 +1,19 @@
|
||||
<!--
|
||||
title: Execute occ in Nextcloud pod
|
||||
-->
|
||||
|
||||
|
||||
First, look up the name of the pod using
|
||||
```
|
||||
kubectl get pods -n nextcloud
|
||||
```
|
||||
|
||||
Then, get into the pod using
|
||||
```
|
||||
kubectl exec --stdin --tty NAME_OF_THE_POD -c nextcloud -n nextcloud -- sh
|
||||
```
|
||||
|
||||
Finally, within the pod
|
||||
```
|
||||
su -s /bin/sh www-data -c "php occ --help"
|
||||
```
|
168
content/snippets/0140-prince-of-persia-1.md
Normal file
168
content/snippets/0140-prince-of-persia-1.md
Normal file
@ -0,0 +1,168 @@
|
||||
<!--
|
||||
title: Solution for Prince of Persia 1
|
||||
-->
|
||||
# Lösung Prince of Persia 1
|
||||
|
||||
## Komplettlösung zu "Prince of Persia 1"
|
||||
|
||||
|
||||
|
||||
Zuallererst mal zur Joysticksteuerung: Wenn Ihr beim
|
||||
Springen den Feuerknopf gedrückt haltet, macht der Prince
|
||||
einen 'Klammersprung', d.h., bei grossen Entfernungen
|
||||
springt er an die gegenüberliegende Wand und klammert sich
|
||||
dort fest. Mit dem Joystick dann einfach nach oben drücken
|
||||
und schon ist's geschafft.
|
||||
|
||||
Ausserdem kann man teilweise Decken aufstossen (VORSICHT,
|
||||
wenn die Platten dann runterfallen!); aber dies ist für das
|
||||
Spiel nur dann nötig, wenn man in einer Sackgasse steckt
|
||||
und der Weg über die Decke weitergeht. Ansonsten sind dort
|
||||
meist 'nur' Potions versteckt. ACHTUNG: Um das Spiel
|
||||
zeitlich zu schaffen empfiehlt es sich, (wenn nicht
|
||||
wirklich nötig) die Deckengänge NICHT zu benutzen. Das
|
||||
Spiel an sich verfügt über 13 Level (12 Level + den
|
||||
Abschlußlevel mit Kampf gegen Jaffar). Wenn man alle Level
|
||||
kennt und perfekt spielt (nie kaputt geht) braucht man
|
||||
trotzdem ca. 45-50 min. Um das Spiel also zu schaffen, muß
|
||||
man in allen Leveln den Weg kennen. Da dies natürlich nicht
|
||||
beim erstenmal klappt ist klar; also immer ein bis zwei
|
||||
Level weiterarbeiten und gut auskundschaften.
|
||||
|
||||
Das Ziel je Level ist simpel:
|
||||
- Türe zum nächsten Level finden
|
||||
- Türe zum nächsten Level öffnen
|
||||
- JEDE Superpotion finden und trinken!!!
|
||||
|
||||
## Die einzelnen Level:
|
||||
|
||||
### Level 1:
|
||||
|
||||
Hier holt Ihr Euch das Schwert
|
||||
|
||||
### Level 2:
|
||||
|
||||
Nix besonderes, allerdings muss man am Ende zum ersten Mal
|
||||
den Klammersprung ausführen.
|
||||
|
||||
### Level 3:
|
||||
|
||||
Dieser Level ist in 2 Teile unterteilt:
|
||||
- Klettert soweit nach oben, wie Ihr könnt, dann einen
|
||||
Sprung in die nicht sichtbare rechte Seite, dort den
|
||||
Türmechanismus betätigen und SCHNELL solange nach links
|
||||
laufen, bis Ihr das sich schließende Tor seht; sofort (aus
|
||||
dem Lauf) einen Klammersprung machen.
|
||||
- Türmechanismus finden und Tür öffnen. Beim Zurücklaufen
|
||||
vorsichtig an das Skelett ranschleichen, es im Kampf die
|
||||
Schlucht runterstoßen, ihm nachklettern und es nochmal
|
||||
besiegen.
|
||||
|
||||
### Level 4:
|
||||
|
||||
Superpotion holen, Türmechanismus betätigen, und durch
|
||||
Spiegel mit Anlauf springen --> Shadow wird geboren (er
|
||||
wird Euch noch einigen Ärger bereiten)
|
||||
|
||||
### Level 5:
|
||||
|
||||
Beim Versuch die Superpotion zu holen, stiehlt sie Euch
|
||||
Shadow. Ihr müßt aber den Versuch trotzdem ausführen!
|
||||
(Erklärung später)
|
||||
|
||||
### Level 6:
|
||||
|
||||
(Sehr kurzer Level) Kämpft mit dem dicken Wächter, indem
|
||||
Ihr auch abwehrt (dazu müßt Ihr den Joystick nach oben
|
||||
drücken). Der Sprung zu Shadow mißlingt und Ihr werdet in
|
||||
Level 7 FALLEN.
|
||||
|
||||
### Level 7:
|
||||
|
||||
Holt Euch die Superpotion (,die man schon am Anfang sieht)
|
||||
und springt dann in die Schlucht hinein, denn die Potion
|
||||
besitzt die magischen Kräfte, Euch fliegen zu lassen.
|
||||
|
||||
### Level 8:
|
||||
|
||||
Den ersten Wächter schafft man leicht mit der
|
||||
Joystickkombination: VOR, HOCH, 2x Feuerknopf (solange
|
||||
wiederholen, bis er tot ist) Wenn Ihr ganz rechts im Level
|
||||
angekommen seit und Euch auf den Weg macht, links den
|
||||
Türmechanismus zu betätigen sind einige Fallen:
|
||||
|
||||
- Der erste Wächter oben ist nur zu schaffen, wenn Ihr
|
||||
schon im vorigen Bild losspringt (er kann dann nicht
|
||||
schnell genug reagieren, trotzdem bekommt Ihr einen Schlag
|
||||
ab!)
|
||||
- Nun müsst Ihr schnell sein (aber immer ruhig und nicht
|
||||
überhasten), da mit dem Türmechanismus 3 (!) Tore auf und
|
||||
zu gehen, also fix durch die Fallmesser.
|
||||
- Wenn Ihr den Türmechanismus betätigt habt und plötzlich
|
||||
nicht mehr nach rechts weiterkommt, müßt Ihr auf eine Maus
|
||||
warten, die den Türmechanismus betätigt (Ahhh!!)
|
||||
|
||||
### Level 9:
|
||||
|
||||
Einfach durchspielen, aber AUFPASSEN: Die erste Superpotion
|
||||
nicht trinken, da sonst der Bildschirm auf dem Kopf steht!
|
||||
Die zweite Superpotion (im Bild nebenan) ist wieder ok und
|
||||
die dritte kehrt den Bildschirm wieder um, falls Ihr die
|
||||
erste getrunken habt. Noch ein Tip: Wenn Ihr das Tor zu
|
||||
Level 10 gefunden habt seht Ihr zwei Säulen; AUF der
|
||||
rechten befindet sich der Mechanismus, der die Tür zur
|
||||
linken Säule öffnet. Ihr MÜSST diesen Mechanismus
|
||||
betätigen.
|
||||
|
||||
### Level 10:
|
||||
|
||||
Zuerst die Wache ganz links töten, dann rechts durch die
|
||||
zwei Fallmesser (2x) hüpfen. Im nächsten Bild den Wächter
|
||||
NICHT fertigmachen, stattdessen oben die Decke einstoßen,
|
||||
hochklettern und von dort OHNE PAUSE nach rechts laufen.
|
||||
|
||||
### Level 11:
|
||||
|
||||
Stoßt im zweiten Bild neben der Säule die Decke auf,
|
||||
klettert hoch und lauft dann OHNE Pause nach rechts zur
|
||||
Superpotion. Vor dem ersten Fallbeil die Decke aufstoßen
|
||||
hochklettern und ganz nach links (ohne Pause) laufen. Wenn
|
||||
Ihr den nächsten Wächter fertiggemacht habt, springt Ihr
|
||||
aus dem Lauf nach rechts und klammert 2x.
|
||||
|
||||
### Level 12:
|
||||
|
||||
Ziemlich tricky! Nach oben klettern, bis ein Weg nach links
|
||||
führt. Diesen ohne Pause durchlaufen und am Ende nach links
|
||||
springen. Hochklettern bis Ihr eine Möglichkeit seht nach
|
||||
rechts zu springen. Hier muss man dann ziemlich schnell 3x
|
||||
nach rechts springen. Es geht dann so ähnlich weiter, bis
|
||||
man auf dem mittleren Turm ganz oben steht. Dort stoßt Ihr
|
||||
die Decke auf, klettert hoch, lauft auf der Plattform ganz
|
||||
nach rechts (Achtung das letzte Teil ist wieder lose),
|
||||
springt dann AUS DEM LAUF nach links und rennt bis zur
|
||||
Wand. Wenn Ihr nun hochklettert, bemerkt Ihr, daß das
|
||||
Schwert fehlt. Ihr geht vorsichtig aber zügig über die 2
|
||||
Fallteile und bleibt dann SOFORT stehen. Shadow springt nun
|
||||
mit gezückter Waffe auf Euch zu. Nun AUF KEINEN FALL mit
|
||||
ihm kämpfen und stattdessen SOFORT Euer Schwert einstecken
|
||||
(Joystick nach unten). Nach der Vereinigung lauft Ihr
|
||||
einfach nach links weiter (nicht wundern, probierts einfach
|
||||
aus, Ihr fallt schon nicht!)
|
||||
|
||||
### Level 13:
|
||||
|
||||
Abwarten bis alles von den Decken gefallen ist, und erst
|
||||
dann los laufen. Jaffar erledigt Ihr am besten, wenn Ihr
|
||||
über das Fallteil auf ihn zu hüpft. Der Kampf ist nicht
|
||||
einfach, da Jaffar über 4! Schlagkombinationen verfügt.
|
||||
Noch einmal VORSICHT. Wenn Ihr ihn besiegt habt lauft Ihr
|
||||
nach rechts, dann wieder nach links (das Tor geht auf),
|
||||
wenn Ihr nun in Richtung Tor nach links geht, springt am
|
||||
besten in das Bild, in dem das Tor ist, da Ihr sonst
|
||||
womöglich in die Schlucht fallt und nochmal kämpfen müsst.
|
||||
Der Rest ist geschenkt und Ihr betretet als Prince of
|
||||
Persia die Hall of fame!!
|
||||
|
||||
Diese Lösung stammt aus Mogel-Power (www.mogelpower.de) / Solution.Net (solution.mogelpower.de)
|
||||
|
13
content/snippets/0150-putty-and-hardware-keys.md
Normal file
13
content/snippets/0150-putty-and-hardware-keys.md
Normal file
@ -0,0 +1,13 @@
|
||||
<!--
|
||||
title: PuTTY and OPENGPG hardware keys
|
||||
-->
|
||||
|
||||
* install gpg4win installed
|
||||
* create or edit the file `gpg-agent.conf`, usually in `c:\Users\XXX\AppData\Roaming\gnupg\`:
|
||||
```
|
||||
enable-putty-support
|
||||
enable-ssh-support
|
||||
use-standard-socket
|
||||
```
|
||||
|
||||
|
14
content/snippets/0160-resize-hdd-on-running-system.md
Normal file
14
content/snippets/0160-resize-hdd-on-running-system.md
Normal file
@ -0,0 +1,14 @@
|
||||
<!--
|
||||
title: Resize HDD on running system
|
||||
-->
|
||||
|
||||
* Resize target on VMWare or on Synology or where ever it is provided
|
||||
* Stop services using the disk
|
||||
* Unmount the disk
|
||||
* Run `e2fsck -f` on the disk
|
||||
* Rescan disks using `echo 1>/sys/class/block/sdx/device/rescan` (replace `sdx` by actual disk device)
|
||||
* Extend partition using `resize` in `cfdisk`
|
||||
* Extend filesystem using `resize2fs` on extended partition
|
||||
* Mount the partition
|
||||
* Start services
|
||||
|
136
content/snippets/0170-rgb-driver.md
Normal file
136
content/snippets/0170-rgb-driver.md
Normal file
@ -0,0 +1,136 @@
|
||||
<!--
|
||||
title: PL 9823 meets MSP430
|
||||
date: 2024-05-25
|
||||
-->
|
||||
|
||||
## Generating signals for PL 9823 using a MSP430
|
||||
|
||||
### Debugging
|
||||
|
||||
```
|
||||
mspdebug rf2500 gdb
|
||||
|
||||
msp430-gdb -x firmware.gdb
|
||||
```
|
||||
|
||||
Attention: the gdb in the TI toolchain package is broken, use the one from Debian
|
||||
|
||||
|
||||
|
||||
### Signals Working Cycler
|
||||
|
||||
These signals are related to code under tag `cycler_works_include_output_stage`.
|
||||
|
||||
First octets:
|
||||
|
||||

|
||||
|
||||
Last octets:
|
||||
|
||||

|
||||
|
||||
Schematics and legend for signals:
|
||||
|
||||

|
||||
|
||||
#### Some more explanations
|
||||
|
||||
Consider above schematics and the screen shot "Last octets" from the oscilloscope.
|
||||
|
||||

|
||||
|
||||
Timer TA1 is running in "up mode" to the value 45 set in compare register `TA1CCR0`. The compare registers `TA1CCR1` is set to 10, `TA1CCR2` is set to 22.
|
||||
The output mode of the timer is set to "Reset/Set", which means the GPIO associated with `TA1CCR1` (P2.1) and `TA1CCR2` (P2.4) are set at the overflow and
|
||||
restart of the counter and reset when the counter matches the associated compare value.
|
||||
|
||||
So, on P2.1 (D1 on the oscilloscope) we have a long pulse and at P2.4 (D0 on the oscilloscope) we have a short pulse, with synchronous raising edge.
|
||||
|
||||

|
||||
|
||||
The inverted signal P2.4 is connected to the Clock input of a 74HC74 D-flipflop, the data input of the flipflop is connected to GPIO P1.0 (D2 on the oscilloscope).
|
||||
|
||||
The interrupt service routine `shifter_isr` is triggered by the overflow and restart of the timer, this interrupt service routine provides the next bit to be
|
||||
signaled on P1.0. This bit is stored at the falling edge of P2.4 (long pulse) in the flipflop.
|
||||
|
||||
The short pulse (P2.1, D1) is ANDed using a 74HC08 with the inverted output of the flipflop, the long pulse (P2.4, D0) is ANDed with the non-inverted output of
|
||||
the flipflop, the ANDed results are ORed using a 74HC32.
|
||||
|
||||
So, at the output of the OR gate (yellow on the oscilloscope) we get a long pulse for a 1 at P1.0 provided by the ISR and a short pulse for a 0 at P1.0.
|
||||
|
||||
The routine `drawscreen` takes color values from the "frame buffer" beginning at `screendata` and translated them into the red, green and blue values and provides these values, first red, then green and finally blue to the ISR via the `DATA_REGISTER`.
|
||||
|
||||
The ISR cycles over the `DATA_REGISTER` and presents the bits at P1.0.
|
||||
|
||||
Additionally, when the first bit of a full draw screen cycle is presented at P1.0 by the ISR, it also sets the data enable signal at P1.1 and when the last bit has been provided it disabled the data enable signal. This signal is also synchronized using a flipflop and used to enable the short/long pulses using an AND gate.
|
||||
|
||||
|
||||
|
||||
### Timing
|
||||
|
||||
Complete cycle: 2.48us
|
||||
|
||||

|
||||
|
||||
Short pulse: 550ns
|
||||
|
||||

|
||||
|
||||
Long pulse: 1.18us
|
||||
|
||||

|
||||
|
||||
|
||||
### Load Time
|
||||
|
||||
During of loading data into five LEDs: 297us
|
||||
|
||||

|
||||
|
||||
During of loading data into six LEDs: 297us
|
||||
|
||||

|
||||
|
||||
|
||||
| # of LEDs | Load Time measured | calculated |
|
||||
| --------- | ------------------ | ---------- |
|
||||
| 5 | 297us | |
|
||||
| 6 | 354us | 356.4us |
|
||||
| 10 | | 594us |
|
||||
| 100 | | 5.9ms |
|
||||
| 200 | | 11.8ms |
|
||||
|
||||
|
||||
### Reset Circuitry
|
||||
|
||||
It appears that the output voltage of the power supply raises that slow, that the MCU
|
||||
will not handle the reset correctly.
|
||||
|
||||
The following circuitry should generate a valid reset signal far enough from the raise
|
||||
of the supply voltage:
|
||||
|
||||

|
||||
|
||||
The circuit generates the following signals:
|
||||
|
||||

|
||||
|
||||
##### Reference voltage (green):
|
||||
|
||||
```math
|
||||
U_ref = 3.3V \frac{22k\Omega}{22k\Omega + 10k\Omega} = 2.2V
|
||||
```
|
||||
|
||||
|
||||
##### Trigger voltage (purple):
|
||||
|
||||
```math
|
||||
U_trigg = 3.3V \frac{330k\Omega}{330k\Omega + 82k\Omega} = 2.64V
|
||||
```
|
||||
|
||||
|
||||
##### RC constant:
|
||||
|
||||
```math
|
||||
\tau = 82k\Omega \cdot 100nF = 8.2ms
|
||||
```
|
||||
|
@ -0,0 +1,12 @@
|
||||
<!--
|
||||
title: snmpwalk with numeric and text output of oid
|
||||
-->
|
||||
|
||||
```
|
||||
snmpwalk -v 2c -c $COMMUNITY -On $HOST $BASE_OID | while read -r line; do
|
||||
oid=`echo $line | awk '{print $1}'`
|
||||
textoid=`snmptranslate $oid`
|
||||
value=`echo $line | cut -d ' ' -f 3-`
|
||||
echo "$oid ($textoid): $value"
|
||||
done
|
||||
```
|
75
content/snippets/0190-tetris.md
Normal file
75
content/snippets/0190-tetris.md
Normal file
@ -0,0 +1,75 @@
|
||||
<!--
|
||||
title: Tetris
|
||||
date: 2024-05-27
|
||||
-->
|
||||
|
||||
# Tetris - Hardware and Software
|
||||
|
||||

|
||||
|
||||
Update Amplifier (separate input circuitry per PSG, it appears, that a silent PSG has a DC level on its output which is summarized to the AC output of the working PSG, so two input circuits with individual couping capacitor):
|
||||
|
||||

|
||||
|
||||
Update of the power switch of the amplifier (at appears, that the small transistor couldn't deliver enough current):
|
||||
|
||||

|
||||
|
||||
This Tetris implementation consists of a hardware and a software (running on that hardware).
|
||||
|
||||
The hardware utilizes four MSP430 microcontrollers for 1.) the game play, 2.) the play ground canvas, 3.) the score display and 4.) the sound effects.
|
||||
|
||||
Further documentation including calculations and drawing can be found in the `docs` subdirs of the four main subdirs.
|
||||
|
||||
## Game Play
|
||||
|
||||
Code is in subdir `game-ctrl` (https://gitea.hottis.de/wn/tetris/src/branch/main/game-ctrl).
|
||||
|
||||
In the firmware for this MSP430 microcontroller the whole game mechanics, reading the buttons, reading and writing the highscore EEPROM and the control of the peripherial microcontrollers are implemented.
|
||||
|
||||
The buttons are debounced using RC circuitry and Schmitt triggers and connected to GPIOs of the microcontroller.
|
||||
|
||||
The peripherial microcontrollers and the EEPROM are connected via SPI including individual chip select lines.
|
||||
|
||||

|
||||
|
||||
|
||||
## Play Ground Canvas
|
||||
|
||||
Code is in subdir `rgb-driver` (https://gitea.hottis.de/wn/tetris/src/branch/main/rgb-driver).
|
||||
|
||||
The play ground is implemented using a 10 * 20 matrix of PL9823 RGB LEDs which are controlled by another MSP430 microcontroller. The firmware for this microcontroller is implemented for performance and real time requirements in assembly code. Through some discret logic the signals for PL9823 LEDs are generated. Major challenge was to generated the signals according the datasheet of all 200 (including a mini canvas for the stone preview: 212) LEDs in real time without interrupts.
|
||||
|
||||
The communcation with the game play controller is implemented as a sequences of tuples of LED address (0 to 211) and color code. A single octet of 253 where the LED address is expected is taken as the end-of-telegram mark. Readiness to receive a telegram is signaled to the game play controller via a single line connected to a GPIO of the game play controller.
|
||||
|
||||

|
||||
|
||||
[Details are here]({{< ref "rgb-driver.md" >}} "Details are here")
|
||||
|
||||
|
||||
## Score Display
|
||||
|
||||
Code is in subdir `display-driver` (https://gitea.hottis.de/wn/tetris/src/branch/main/display-driver).
|
||||
|
||||
In the first place, a MAX7221 was meant to be used for connecting a multiple digit seven-segment display. However, it appears, that the MAX7221 requires 3.5V as minimum voltage for the high-level, which caan't be provided by the MSP430 (which runs on 3.3V) and level-shifters haven't been around. Thus, the minimal required amount of functionality of the MAX7221 has been implemented in C on an MSP430. Just four digits are supported.
|
||||
|
||||
Communication with the game play controller is just a 16 bit number to be displayed.
|
||||
|
||||

|
||||
|
||||
|
||||
## Sound Effects
|
||||
|
||||
Code is in subdir `sound-driver` (https://gitea.hottis.de/wn/tetris/src/branch/main/sound-driver).
|
||||
|
||||
An MSP430 microcontroller and two mediaeval AY-3-8913 sound chips are deployed. The sound chips themselve run on 5V, their 8-bit-address/data bus is connected to the port 2 (bit 0 to 7) of the microcontroller. The bus control signal `_CS`, `BC1` and `BDIR` are generated in software and provided via GPIOs.
|
||||
|
||||
An amplifier following the proposal of the AY-3-8913 datasheet is implemented using a LM386 chip. A MOSFET BS108 controlled via a GPIO is use the shortcut the input of the amplifier to ground to mute sound effects.
|
||||
|
||||
The clock generator proposed by the AY-3-8913 does not work reliably, so an alternative design from "The Art of Electronics" has been used.
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
67
content/snippets/0200-theremin.md
Normal file
67
content/snippets/0200-theremin.md
Normal file
@ -0,0 +1,67 @@
|
||||
<!--
|
||||
title: Theremin
|
||||
date: 2013-07-01
|
||||
-->
|
||||
A [Theremin](https://en.wikipedia.org/wiki/Theremin) is a rather old electronic music instrument, invented in 1928. It is played by approaching hands to two antennas, without touching them. One antenna is used to manipulate the frequeny of the tone, the other one to manipulate the volume.
|
||||
|
||||

|
||||
|
||||
This is just another Theremin. Only basic structure of the circuit was taken from many other published Theremin circuits.
|
||||
|
||||

|
||||
|
||||
Completely new (or at least not found during my Theremin googling) is the digital zero-calibration.
|
||||
|
||||
The both left-hand-side oscillators together with the mixer+filter block provide the signal to control the volume, the right-hand-side oscillators and mixer+filter block provide the signal to control the frequency.
|
||||
|
||||
Each of these both couples consists of two oscillators and a mixer+filter block. Both oscillators have to swing on exactly the same frequency, in this case of about 1.3MHz. While the exact frequency does not matter, it is significant that both oscillators have the same frequency. The signals of both oscillators will be mixed, which means, multiplied.
|
||||
|
||||
$$\sin(\omega_0 t) sin(\omega t)$$
|
||||
|
||||
Here $\omega$ is the frequncy of one of the oscillators while $\omega_0$ is the frequency of the other one.
|
||||
|
||||
This term can be modified using the addition rule for trigonometric functions into
|
||||
|
||||
$$\frac{\cos((\omega_0-\omega)t)-\cos((\omega_0+\omega)t)}{2}$$
|
||||
|
||||
Due to this transformation, two signals, one with the sum and one with the difference of both input signal frequencies, are accumulated.
|
||||
When both frequencies are exactly the same, one part of the sum appears as a DC offset, while the other part is the doubled frequency.
|
||||
If one oscillator is de-tuned by only a few Hz'`s, one part are this few Hz'`s (a very low, hearable frequency) and the other part is still (roughly) the doubled frequency (a high frequency). The high frequency part can now be suppressed using a lowpass-filter.
|
||||
Multiplication of two signals can be done using an analog four quadrant multiplier, like the AD633. So, this is the schematic of the mixer+filter block:
|
||||
|
||||

|
||||
|
||||
The output signal of this block is the difference of the detuning of the one oscillator.
|
||||
|
||||
Detuning of the oscillator will be achieved by approaching the hand to the antenna of the oscillator.
|
||||
|
||||

|
||||
|
||||
The antenna acts as a kind of a capacitive sensor and by approaching the hand a very small amount of capacity is added into the LC resonator.
|
||||
|
||||
The other oscillator is a fix-frequency oscillator which can be tuned to swing on the same frequency as the first oscillator in a not detuned state.
|
||||
|
||||

|
||||
|
||||
This tuning is achieved by biasing the two varactor diodes.
|
||||
|
||||
Here is automated tuning circuit steps in:
|
||||
|
||||

|
||||
|
||||
The low-frequency output signal of the mixer+filter block is provided through a 2-to-1 multiplexer (the four NAND-gates) into a microcontroller. The microcontroller measures the frequency and as long as it is above a frequency $\epsilon$ of say 10Hz, the bias voltage $U_{tune}$ is increased.
|
||||
|
||||
These both oscillators with mixer+filter and one channel of the zero-calibration appear twice in the whole circuit, one for frequency manipulation and one for volume manipulation.
|
||||
|
||||
The low-frequency, hearable, signal and the volume-control signal are brought together in the volume-control circuit
|
||||
|
||||

|
||||
|
||||
Here, the low-frequency signal $U_{Lf1}$ is passed through a high-pass filter. The high-pass filter is calculated that way that the whole detunable frequency range comes onto the ramp of the filter. So, the not detuned output signal of the mixer+filter is a DC signal, which is suppressed completely by the high-pass filter (beginning of the ramp) and the maximum detuned output signal of about 2kHz matched roughly to the end of the ramp. This filtered signal is rectified and only the negative half-wave of the signal passes the diode. This half-wave signal is sieved by the larger capacitor to get a DC signal between 0 and the maximum amplitude which passed the fiter. This negative DC signal is fed into the FET, which is configured as a voltage controlled resistor. This voltage controlled resistor and the fix resistor (5k6) are building a voltage controlled voltage divider. The hearable frequency signal $U_{Lf2}$ is fed into this voltage divider and passed to an amplifier.
|
||||
|
||||
The output signal of this block in turn is the volume-controlled and frequency-controlled signal which is the output signal of this Theremin. It is passed into a power-amplifier and into a speaker - done.
|
||||
|
||||
[Calibrating the Theremin](https://www.youtube.com/watch?v=5US8LY_FbQ4&w=420&h=315)
|
||||
|
||||
[Playing the Theremin](https://www.youtube.com/watch?v=lDld71HI66o&w=420&h=315)
|
||||
|
25
content/snippets/0210-three-phase-inverter-ng.md
Normal file
25
content/snippets/0210-three-phase-inverter-ng.md
Normal file
@ -0,0 +1,25 @@
|
||||
<!--
|
||||
title: Three Phase Inverter - Second Service
|
||||
date: 2016-12-19
|
||||
-->
|
||||
|
||||
I wrote in October about my first try to build a simple three phase inverter, see [here]({{< ref "three-phase-inverter.md" >}}). In the first try I used four MSP430 microcontroller, one for the PWM of each phase and one to coordinate the phase shift of the three phases.
|
||||
|
||||
In this experiment I put everything on one STM32 microcontroller. Here I used the DMA feature to feed data into the PWM counter and I calculated the sine values at start-up time on the microcontroller. Additionally I put in the driver for a CAN interface, however, it is not yet supported in the firmware.
|
||||
|
||||

|
||||
|
||||
From top to bottom you see the CAN driver, the STM32 board, opto coupler to separate logic and power part and then from right to left in the bottom half the low-side/high-side MOSFET drivers and the MOSFETs.
|
||||
|
||||

|
||||
|
||||
The power supply consists of a traditional transformer and (top right) the rectifier and capacitors for the power part, together with the 12V regulator for the drivers and (top left) the regulators for 3.3V and 5V for the logic part.
|
||||
|
||||

|
||||
|
||||
The motor is the same as in the earlier experiment - I don't have too much of them. And everything is put onto one board:
|
||||
|
||||

|
||||
|
||||
The code for this experiment is here: [https://gitea.hottis.de/wn/inverter2](https://gitea.hottis.de/wn/inverter2).
|
||||
|
44
content/snippets/0220-three-phase-inverter.md
Normal file
44
content/snippets/0220-three-phase-inverter.md
Normal file
@ -0,0 +1,44 @@
|
||||
<!--
|
||||
title: Three Phase Inverter
|
||||
date: 2016-10-14
|
||||
-->
|
||||
|
||||
|
||||
Already when I was still in school, about 30 years ago, I was curious to make an inverter using some MOSFETs. I actually was able to build a simple one phase inverter with rectangular signal shape (I used a NE555). Using this thing I drove a transformer to light a blub. However, all of these inverters I built passed by in fire.
|
||||
|
||||
Now, I tried it again, not longer using MOSFETs but IGBTs with free-wheeling diode. Moreover, I used some microcontrollers and sine values to feed a PWM to get a sine-alike signal shape. And this time I was able with three phases to drive an asynchronous motor.
|
||||
|
||||

|
||||
|
||||
The signal shaping is done with four MSP430 controllers, three as PWMs to drive the bridge and one to coordinate and control the three PWMs. The PWM controller is decoupled from the IGBT driver (IR2184) using optic couplers.
|
||||
|
||||

|
||||
|
||||
The bridge is a three phase IGBT module is a 6MB120F-060 I got for a few euros at ebay.
|
||||
|
||||

|
||||
|
||||
To avoid high voltages in my setup I got a 24V async motor, also from ebay.
|
||||
|
||||

|
||||
|
||||
The PWMs generate the signal from a sine table generated using Excel. Those I got this signal:
|
||||
|
||||

|
||||
|
||||
The main task of the coordinator is the start the PWMs with a phase shift of 120° (digital line 1, 2 and 3):
|
||||
|
||||

|
||||
|
||||
Currently the PWMs start with random polarity. The interesting signals are the digital lines 4, 5 and 6.
|
||||
|
||||
Sometimes the motor runs:
|
||||
|
||||

|
||||
|
||||
But sometimes not:
|
||||
|
||||

|
||||
|
||||
The firmware is available here [https://gitea.hottis.de/wn/inverter0](https://gitea.hottis.de/wn/inverter0) and [https://gitea.hottis.de/wn/inverter0ctrl](https://gitea.hottis.de/wn/inverter0ctrl).
|
||||
|
37
content/snippets/0230-timeserver2.md
Normal file
37
content/snippets/0230-timeserver2.md
Normal file
@ -0,0 +1,37 @@
|
||||
<!--
|
||||
title: Stratum 1 NTP Server participating in ntppool.org
|
||||
date: 2025-03-13
|
||||
-->
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
[Details at ntppool.org](https://www.ntppool.org/scores/93.241.86.156)
|
||||
|
||||
## Harrison
|
||||

|
||||

|
||||
|
||||
Setup details for this machine are here: [https://gitea.hottis.de/wn/harrison-setup](https://gitea.hottis.de/wn/harrison-setup).
|
||||
|
||||
The snmpd subagent for monitoring the ntp daemon is here: [https://gitea.hottis.de/wn/snmp-agentx-ntpsec](https://gitea.hottis.de/wn/snmp-agentx-ntpsec).
|
||||
|
||||
### Details of Setup
|
||||
|
||||
A GPS receiver (ublox Neo-6M) is connected via a RS232 level converter (MAX232) and via the RS232 connection to a machine (it was not easy to find one with RS232) with a Debian installation.
|
||||
|
||||
The PPS signal of the GPS receiver is transmitted via the DCD line of the RS232 connection. That in turn is evaluated by the NMEA line discipline of Linux.
|
||||
|
||||
The GPS receiver is then configured as a reference clock in ntpsec:
|
||||
|
||||
```
|
||||
refclock nmea unit 0 mode 0x10 minpoll 4 maxpoll 4 path /dev/ttyS0 ppspath /dev/pps0 baud 9600 flag1 1 flag2 1 flag3 0 refid LIgp
|
||||
```
|
||||
|
||||
|
||||
## David
|
||||

|
||||
|
||||
Details on the setup of this machine are described here: [https://minimal-setups.de/blog/timeserver/](https://minimal-setups.de/blog/timeserver/).
|
||||
|
129
content/snippets/0240-timeserver.md
Normal file
129
content/snippets/0240-timeserver.md
Normal file
@ -0,0 +1,129 @@
|
||||
<!--
|
||||
title: Just another Stratum 1 Timeserver
|
||||
date: 2025-02-11
|
||||
-->
|
||||
|
||||
|
||||

|
||||
|
||||
This server utilizes `ntpsec` on Debian on a BeagleBone Black with a UBlox GPS module.
|
||||
|
||||
It has been joined the NTP pool, the statistics are available at [https://www.ntppool.org/scores/93.241.86.156](https://www.ntppool.org/scores/93.241.86.156).
|
||||
|
||||
Some additional statistics graphs for the server are available at [https://numbers.hottis.de/ntpserver](https://numbers.hottis.de/ntpserver).
|
||||
|
||||
|
||||
## Preparation of the BeagleBone
|
||||
|
||||
The GPS module is connected via serial line to the UART of the BB.
|
||||
|
||||
The additional connection of the PPS output with the PPS device of the Linux running on the BB via a GPIO must be prepared. A device tree overlay must be created and compiled:
|
||||
|
||||
```
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/{
|
||||
compatible = "ti,beaglebone", "ti,beaglebone-black";
|
||||
part_number = "WN-PPS";
|
||||
version = "00A0";
|
||||
|
||||
exclusive-use =
|
||||
"P8.7",
|
||||
"gpio2_2";
|
||||
|
||||
fragment@0 {
|
||||
target = <&am33xx_pinmux>;
|
||||
__overlay__ {
|
||||
bs_pinmode_P8_7_0x27: pinmux_bs_pinmode_P8_7_0x27 {
|
||||
pinctrl-single,pins = <0x090 0x27>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@1 {
|
||||
target = <&ocp>;
|
||||
__overlay__ {
|
||||
bs_pinmode_P8_7_0x27_pinmux {
|
||||
compatible = "pps-gpio";
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&bs_pinmode_P8_7_0x27>;
|
||||
gpios = <&gpio2 2 0>;
|
||||
assert-rising-edge;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
This file shall be compiled using
|
||||
|
||||
```
|
||||
dtc -O dtb -o WN-PPS-00A0.dtbo -b 0 -@ WN-PPS-00A0.dts
|
||||
```
|
||||
|
||||
The binary dtbo file then copied into `/lib/firmware` and mentioned in the `/boot/uEnv.txt`:
|
||||
|
||||
```
|
||||
uboot_overlay_addr0=/lib/firmware/WN-PPS-00A0.dtbo
|
||||
```
|
||||
|
||||
After a reboot the device file `/dev/pps0` should be available and using `ppstest /dev/pps0` you can test the connection:
|
||||
|
||||
```
|
||||
root@david:/boot# ppstest /dev/pps0
|
||||
trying PPS source "/dev/pps0"
|
||||
found PPS source "/dev/pps0"
|
||||
ok, found 1 source(s), now start fetching data...
|
||||
source 0 - assert 1739442756.999984966, sequence: 306598 - clear 0.000000000, sequence: 0
|
||||
source 0 - assert 1739442757.999978472, sequence: 306599 - clear 0.000000000, sequence: 0
|
||||
source 0 - assert 1739442758.999976057, sequence: 306600 - clear 0.000000000, sequence: 0
|
||||
^C
|
||||
root@david:/boot#
|
||||
```
|
||||
|
||||
|
||||
## Configuration of the ntpsec daemon
|
||||
|
||||
|
||||
```
|
||||
interface listen all
|
||||
logconfig +all
|
||||
logfile /var/log/ntp.log
|
||||
|
||||
statsdir /var/log/ntpsec/
|
||||
statistics loopstats peerstats clockstats protostats sysstats rawstats
|
||||
filegen loopstats file loopstats type day disable
|
||||
filegen peerstats file peerstats type day enable
|
||||
filegen clockstats file clockstats type day enable
|
||||
filegen protostats file protostats type day enable
|
||||
filegen sysstats file sysstats type day enable
|
||||
filegen rawstats file rawstats type day disable
|
||||
|
||||
driftfile /var/lib/ntpsec/ntp.drift
|
||||
leapfile /usr/share/zoneinfo/leap-seconds.list
|
||||
|
||||
tos maxclock 11
|
||||
tos minclock 4 minsane 3
|
||||
|
||||
refclock nmea unit 0 prefer mode 0x10 minpoll 4 maxpoll 4 path /dev/ttyO4 ppspath /dev/pps0 baud 9600 flag1 1 refid BBgp
|
||||
# refclock shm unit 0 refid BBg minpoll 4 maxpoll 4 time1 0.1555
|
||||
# refclock shm unit 2 refid BBp minpoll 4 maxpoll 4 prefer
|
||||
# refclock pps unit 0 prefer refid BBp ppspath /dev/pps0 minpoll 4 maxpoll 4
|
||||
# refclock gpsd unit 0 prefer refid BBgp mode 1 minpoll 4 maxpoll 4
|
||||
|
||||
server ntps1-1.uni-erlangen.de
|
||||
server ntps1-0.cs.tu-berlin.de
|
||||
server ptbtime1.ptb.de
|
||||
server rustime01.rus.uni-stuttgart.de
|
||||
server ntp1.sda.t-online.de
|
||||
server ntps1.gwdg.de
|
||||
|
||||
restrict default kod nomodify nopeer noquery limited notrap
|
||||
restrict 127.0.0.1
|
||||
restrict ::1
|
||||
```
|
||||
|
||||
Although the `nmea` reference clock driver is obsolete according to [https://ntpsec.org/removal-plan.html](https://ntpsec.org/removal-plan.html), it works perfectly for me, in particular better then the other drivers. However, maybe I was not trying hard enough with the others.
|
||||
|
15
content/snippets/9999-quotes.md
Normal file
15
content/snippets/9999-quotes.md
Normal file
@ -0,0 +1,15 @@
|
||||
<!--
|
||||
title: Quotes
|
||||
-->
|
||||
|
||||
# Quotes
|
||||
|
||||
Und dann in deinem Arm, alles gut, alles andere egal
|
||||
(Dota Kehr, Alles Du)
|
||||
|
||||
Es ist immer was los, aber es passiert nichts.
|
||||
(Thadeuz, Steinhammer)
|
||||
|
||||
Sie steht gut da. Aber die Seele setzt sich nicht dazu.
|
||||
(Thadeuz, Steinhammer)
|
||||
|
Reference in New Issue
Block a user