1
0

Compare commits

..

9 Commits

25 changed files with 1144 additions and 807 deletions

View File

@ -46,7 +46,7 @@ import EquipmentPage from './Pages/Radio/equipmentPage';
import PlamoMain from './Pages/Plamo/PlamoMain'
import { languages, getLanguage } from './Language/Language';
import { japaneseRoutes, plamoBlogRoutes, programmingLanguageRoutes } from './Routers';
import { japaneseRoutes, plamoBlogRoutes, plamoEquipmentRoutes, programmingLanguageRoutes } from './Routers';
function App() {
const language = getLanguage();
@ -130,24 +130,25 @@ function App() {
{/* Plamo */}
{plamoBlogRoutes}
{plamoEquipmentRoutes}
{/* Software */}
{programmingLanguageRoutes}
<Route exact path='/software/dxp-development' element={<DXPDevelopment />}></Route>
<Route exact path='/software/configuration-automation' element={<ConfigAutomation />}></Route>
<Route exact path='/software/wifi-prototype' element={<WifiPrototype />}></Route>
<Route exact path='/software/embedded-game' element={<SwivForPi />}></Route>
<Route exact path='/software/raspberry-pi-jukebox' element={<RaspberryJukebox />}></Route>
<Route exact path='/software/kanji-application' element={<KanjiApplication />}></Route>
<Route exact path='/software/attachment-module' element={<AttachmentModule />}></Route>
<Route exact path='/software/teslamaze' element={<TeslaMaze />}></Route>
<Route exact path='/software/embedded-internet-radio' element={<EmbeddedInternetRadio />}></Route>
<Route exact path='/software/windows10-cookbook' element={<Windows10Cookbook />}></Route>
<Route exact path='/software/ios-airports' element={<IOSAirports />}></Route>
<Route exact path='/software/festival-simulator' element={<FestivalSimulator />}></Route>
<Route exact path='/software/boebot' element={<BoardOfEducationBot />}></Route>
<Route exact path='/software/metroid-horizontal-shooter' element={<MetroidShooter />}></Route>
<Route exact path='/en/software/project/dxp-development' element={<DXPDevelopment />}></Route>
<Route exact path='/en/software/project/configuration-automation' element={<ConfigAutomation />}></Route>
<Route exact path='/en/software/project/wifi-prototype' element={<WifiPrototype />}></Route>
<Route exact path='/en/software/project/embedded-game' element={<SwivForPi />}></Route>
<Route exact path='/en/software/project/raspberry-pi-jukebox' element={<RaspberryJukebox />}></Route>
<Route exact path='/en/software/project/kanji-application' element={<KanjiApplication />}></Route>
<Route exact path='/en/software/project/attachment-module' element={<AttachmentModule />}></Route>
<Route exact path='/en/software/project/teslamaze' element={<TeslaMaze />}></Route>
<Route exact path='/en/software/project/embedded-internet-radio' element={<EmbeddedInternetRadio />}></Route>
<Route exact path='/en/software/project/windows10-cookbook' element={<Windows10Cookbook />}></Route>
<Route exact path='/en/software/project/ios-airports' element={<IOSAirports />}></Route>
<Route exact path='/en/software/project/festival-simulator' element={<FestivalSimulator />}></Route>
<Route exact path='/en/software/project/boebot' element={<BoardOfEducationBot />}></Route>
<Route exact path='/en/software/project/metroid-horizontal-shooter' element={<MetroidShooter />}></Route>
<Route exact path='/books' element={<Books books={booksdata.books} />}></Route>
<Route exact path='/linux' element={<Linux />}></Route>

View File

@ -39,10 +39,26 @@ const languageStrings = {
nvisAntenna: 'NVIS Antenna',
totalUniqueQSO: 'total unique QSO',
// Scale Model
plamo: 'Plamo',
scalemodel: 'Scale model',
// Software
code_pages: 'Code sections',
code_pages_intro: 'Some notes and examples of code.',
software_projects: 'Projects',
// Projects
attachment_module: 'Attachment module',
boebot: 'Board of Education robot',
dxp_development: 'DXP development',
embedded_internet_radio: 'Embedded internet radio',
embedded_game: 'Embedded game',
ios_airports: 'iOS airport',
festival_simulator: 'Festival simulator',
kanji_application: 'Kanji applicatition',
metroid_horizontal_shooter: 'Horizontale shooter game',
raspberry_pi_jukebox: 'Raspberry Pi Jukebox',
teslamaze: 'TeslaMaze',
wifi_prototype: 'Wi-Fi prototype board',
windows10_cookbook: 'Windows 10 cookbook',
// Footer
footer_contentparsed: 'Content is parsed by',
footer_madewith: 'This site was made with',
@ -85,10 +101,27 @@ const languageStrings = {
nvisAntenna: 'NVIS antenne',
totalUniqueQSO: 'totaal unieke QSO',
// Scale Model
plamo: 'Plamo',
scalemodel: 'Schaalmodel',
// Software
code_pages: 'Code secties',
code_pages_intro: 'Notities en voorbeelden van code.',
software_projects: 'Projecten',
// Projects
attachment_module: 'Attachment module',
boebot: 'Board of Education robot',
dxp_development: 'DXP development',
embedded_internet_radio: 'Embedded internet radio',
embedded_game: 'Embedded spel',
ios_airports: 'iOS luchthavens',
festival_simulator: 'Festival simulator',
kanji_application: 'Kanji applicatie',
metroid_horizontal_shooter: 'Horizontale shooter',
raspberry_pi_jukebox: 'Raspberry Pi Jukebox',
teslamaze: 'TeslaMaze',
wifi_prototype: 'Wi-Fi prototype board',
windows10_cookbook: 'Windows 10 kookboek',
// Footer
footer_contentparsed: 'Inhoud is verwerkt door',
footer_madewith: 'Deze website is gemaakt met',

View File

@ -1,86 +0,0 @@
# Airbrush booth
I built a simple diy airbrush booth in November 2024, here is the progress I made on it.
First I needed space, the bike shed below our appartment would suit well. I cleaned up everything and moved an old school desk to where I wanted my booth.
[foto1]
I started with some planks I wanted to use as foundation and to raise the entire booth a bit. These planks were left over from a old plant container I had on our balcony and tore down. I drilled holes, sanded the sides and glued some wooden dowels in.
[foto2]
[foto3]
Then saw the side panels and the back panel.
[foto4]
Saw the bars that would go in the corners, I thought these 45 degree bars looked nice from the inside.
I sawed off some of the top, so that cables for the lights could go behind these bars later.
[foto5]
[foto6]
There is no need for this many dowels, just a few is enough. I was unable to fit them together because at some point, some dowels did not exactly match up with the opposite holes, so it did not fit. I had to saw off some of the dowels until it would fit.
[foto7]
The 45 degree cut bars would have looked nice, but these bars proved difficult when I had to glue them together. I could not clamp it together, not even with another 45 degree bar on the opposite side. The opposite bar just kept sliding out of place. I considered this a failure and tore it apart before the glue could cure. I sanded the glue off and decided to just take a square bar instead for these corners.
[foto8]
[foto9]
This went much easier, I cut 2 bars to length, and again removed some of the tops for the cables.
[foto10]
[foto11]
I tried to glue a corner together, but it did not line up perfectly nice, some of the dowels were a bit too long I thing, which I did underestimated when dry-fitting.
[foto12]
For the next corner, I decided to do it more simple. Just 3 dowels and glue it to the edge, nothing more. Once dried, sand it to make the sides even. This worked rather well.
[foto13]
[foto14]
Again, add just a few dowels for the back panel, and glue together.
---
Next I decided to work on the planks that would form the base and carry the whole cabine. These were not the most even pieces of wood to work with and required a lot of planing to get them (a little bit) even. I wanted to do this myself and reuse these planks, but going to a workshop to have these planed would have saved a lot of time and effort.
[foto15]
[gifje1]
[foto16]
It took a few days to get them to be even enough, I then moved on to make the lid.
I cut four blocks from the bar I used for the corner to put on the lid and glued it together.
[foto17]
I was not confident I could line up the dowels on the opposite side, so I just drilled through the blocks and hammered the dowels through them. Sadly I hit one dowel a little too hard, which almost went through the front. But it will be an easy fix later.
[foto18~21]
Next come two holes in the lid for the ventilation. I drew a circle, drilled holes and then cut out the rest with a mortise chisel (schietbeitel). I made another mistake here, because I drew the inner diameter to be cut out.
[foto22~23]
Since the ventilation part is a few millimeters thick, of course it would not fit. To fix this, I used a rasping file to get rit of a few more millimeters of wood.
[foto24]
After both holes were made in the lid, I filled up some uneven and broken parts with wood plaster. Then I put on an undercoat of white paint on the wood.
After sanding the undercoat and then re-applying it again, I painted some white lacquer on the entire assembly with a paint roller. It is not necessary, but it does give it a nicer finish than just the white undercoat of paint.

View File

@ -1,11 +1,9 @@
# Scale modelling
# Plamo
Building and painting scale models is one of my hobbies. Here is a collection of the things I made and use.
Building and painting plastic scale models and mecha figures is one of my hobbies. Here is a collection of the things I made and use.
---
## Blog
### Equipment
* [Airbrush booth](./blog/airbrush-cabine)
* [Airbrush booth](./equipment/airbrush-cabine)

View File

@ -0,0 +1,235 @@
# Airbrush booth
I started building a simple airbrush booth in November 2024, here is the progress I made on it. It was completed in February 2025. Note, an airbrush booth can be made far simpler and cheaper. A purchased one is probably even better. I even used a simple cardboard box the first time, which serves the purpose well. This booth was just a fun project for me to make.
---
First I needed space, the bike shed below our appartment would suit well. I cleaned up everything and moved an old school desk to where I wanted my booth.
2024-11-03
![mess in bike shed](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-03-cleanup)
### Woodwork
I started with some planks I wanted to use as foundation and to raise the entire booth a bit. These planks were left over from a old plant container I had on our balcony and tore down. I drilled holes, sanded the sides and glued some wooden dowels in.
2024-11-06
![dowels and drill](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-06-duvels-boormachine)
![glueing foundation](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-07-fundering-lijmen)
Then saw the side panels and the back panel.
2024-11-16
![sawing panels](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-16-wanden-zagen)
Saw the bars that would go in the corners, I thought these 45 degree bars looked nice from the inside. Later I would regret using these bars though.
![sawing 45 bar](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-16-mastieklat-zagen)
I sawed off some of the top, so that cables for the lights could go behind these bars later.
2024-11-19
![45 bar cutouts](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-19-mastieklat-uitsparing)
There is no need for this many dowels, just a few is enough. I was unable to fit them together because at some point, some dowels did not exactly match up with the opposite holes, so it did not fit. I had to saw off some of the dowels until it would fit.
![too many dowels](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-19-veel-te-veel-duvels)
The 45 degree cut bars would have looked nice as corners, but these bars proved difficult when I had to glue them together. I could not clamp it together, not even with another 45 degree bar on the opposite side. The opposite bar just kept sliding out of place. I considered this a failure and tore it apart before the glue could cure. I sanded the glue off and decided to just take a regular bar instead for these corners.
2024-11-20
![glueing 45 bar](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-20-mastieklat-lijmen)
![45 bar not flat](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-20-mastieklat-niet-egaal)
This went much easier, I cut 2 bars to length, and again removed some of the tops for the cables.
2024-11-23
![sawing bar](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-23-balken-zagen)
![bar cutouts](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-23-balken-uitsparing)
I tried to glue a bar to panel, but it did not line up perfectly, some of the dowels were a bit too long I think, which I underestimated when dry-fitting.
2024-11-24
![bar glueing 1](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-23-balk-lijmen-1)
![bar glueing 2](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-24-balk-lijmen-2)
![bar glueing 3](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-24-balk-lijmen-3)
When dry-fitting, it works better to mark the dowel with a pencil. That way, you know exactly how deep it goes in the opposite hole.
2024-11-25
![dowel marking 1](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-25-duvel-aftekenen-1)
![dowel marking 2](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-25-duvel-aftekenen-2)
For the next corner, I decided to do it more simple. Just 3 dowels and glue it to the edge, nothing more. Once dried, sand it to make the sides even. This worked rather well. Again, add just a few dowels for the back panel, and glue together.
![bar glueing 4](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-25-balk-lijmen-4)
![bar glueing 5](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-25-balk-lijmen-5)
### Planing
Next I decided to work on the planks that would form the base and carry the whole cabine. These were not the most even pieces of wood to work with and required a lot of planing to get them (a little bit) even. I wanted to do this myself and reuse these planks, but going to a workshop to have these planed would have saved a lot of time and effort. But, I think planing by hand is very rewarding effort.
2024-11-27
![planing 1](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-27-planing-1)
![planing 3](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-27-planing-3)
All panels glued together on top of the foundation planks and the glass plate. This glass plate I found near the trash, it was a nice thick plate without any damage. Propably was part of a coffee table.
2024-11-28
![all panels](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-28-alle-wanden)
### The lid
I then moved on to make the lid. I cut four blocks from the bar I used for the corner to put on the lid and glued it together. I was not confident I could line up the dowels on the opposite side, so I just drilled through the blocks and hammered the dowels through them. Sadly I hit one dowel a little too hard, which almost went through the front. But it will be an easy fix later. The lid will not be glued to the other panels, so it can be taken off and moved later.
2024-12-07
![lid blocks 1](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-07-deksel-blokjes-1)
![lid blocks 2](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-07-deksel-blokjes-2)
![glueing the lid](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-07-deksel-lijmen)
2024-12-08
![airbrush booth with the lid](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-08-cabine-met-deksel)
Next come two holes in the lid for the ventilation. I drew a circle, drilled holes and then cut out the rest with a mortise chisel (schietbeitel). I made another mistake here, because I drew the inner diameter to be cut out.
2024-12-08
![cutting holes in lid 1](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-08-deskel-gaten-1)
![cutting holes in lid 2](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-08-deskel-gaten-2)
Since the ventilation part is a few millimeters thick, it would not fit. To fix this, I used a rasping file to get rit of a few more millimeters of wood.
2024-12-13
![cutting holes in lid 3](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-13-deksel-gaten-3)
![cutting holes in lid 4](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-17-deksel-gaten-4)
After both holes were made in the lid, I filled up some uneven and broken parts with wood plaster. Then I put on an undercoat of white paint on the wood.
### Painting
Here you can see the dowel I almost bashed through the front. But some sanding fixed that and the paint will hide all uneveness later.
2024-12-20
![fixing the front](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-20-frontje-fixen)
Then the whole assembly could be painted with an undercoat of primer.
2024-12-23
![undercoat painting](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-23-onderlaag-verf)
After sanding the undercoat and then re-applying it again, I painted some white lacquer on the entire assembly with a paint roller. It is not necessary, but it does give it a nicer finish than just the white undercoat of paint.
2025-01-03
![paints](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-26-verfpotten)
![fully painted booth](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-03-geverfde-cabine)
### Electronics
My shed had a few wires leading to the bike shed, which I will utilize to build the other electronics.
2025-01-11
![old electronics setup](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-11-oude-elektronica)
I was going to mount the T-section for the ventilation to the wall as well with some hose clamps.
![hose clamps on the wall](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-11-beugels)
The following electronics had to be mounted:
* A main switch for the ventilator.
* A switch to toggle between full speed and half speed for the ventilator.
* A switch for the LED inside the booth.
* A power converter to DC for the LEDs.
* A dimmer for the LEDs.
And while I was busy, I also decided to replace all the lights in the shed itself with LED strips, reusing the existing switch/outlet combination.
I attempted to be efficient with space first, by trying to cram as many wires as possible into the PVC tubes. But this was very hard to work with and turned out to be a big mess. I tore everything down again and tried a different approach.
2025-01-11
![plan A](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-11-plan-A)
The second plan was better, I made "modules" (labeled 1, 2 and 3) with incoming and outgoing wires. They would then come together into a box in the middle. This turned out well, it allowed me to work separately on each module. The box later turned out to be easily expandible as well, when I added one more line for the compressor.
2025-01-15
![plan B](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-15-plan-B)
All the wires were going to be guided through white 5/8 inch PVC pipes. In order to bend them, I clamped a heat gun to the table, shoved a special spring into the pipe in order to bend them with both hands. Worked rather well, but I can only guide the wires through a single bend. I bended the pipes twice, but it was impossiple to get the wires through for me. I then cut those pipes in half after bending, put the wires in and taped them back together again.
2025-01-18
![bending P V C pipes with heat gun](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-18-pvc-buigen-hittepistool)
The new electronics setup.
2025-01-19
![new electronics setup](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-19-nieuwe-elektronica)
And then the hoses could be attached for the ventilation.
![setup with hoses attached](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-19-nieuwe-setup-met-slangen)
Next work had to be done to make the LED strips. Soldering direcly to the strips proved a little difficult by hand only, so I decided to invest in some good extra hands from Weller. I used extra hands before, but these bendable clamps from Weller are perfect and made soldering a breeze.
2025-01-25
![soldering equipment](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-25-solderen)
On this picure the wires were still a little too short, so I extended them a bit later.
2025-01-31
![L E D strips](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-31-led-strips)
At one point I thought it would be nice to have an extra outlet near the floor for the compressor as well, along with a switch so I can easily reach it. The little box was just big enough to fit all the connections at this point.
![extra line for the compressor](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-31-compressor-lijn)
![connection box](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-31-lasdoosje)
### Completion
I attached 4 strips, on each side of the lid. The final result is a nice box that provides day coloured light from every angle.
2025-02-09
![final light setup](/images/plamo/equipment/workplace/airbrush-cabine/2025-02-09-final-light-setup)
My friend told me it looks a bit like a hangar, here is a 1/144 Zaku II for scale.
![zaku hangar](/images/plamo/equipment/workplace/airbrush-cabine/2025-02-09-zaku-hangar)
Finally completed and inspired by the hangar remark, I decided to name my booth: ["White Base"](https://en.wikipedia.org/wiki/White_Base).

View File

@ -0,0 +1,235 @@
# Airbrush cabine
Ik ben begonnen met het bouwen van een airbrush-cabine in november 2024 en afgemaakt in februari 2025, hier is een artikel over de voortgang. Het is mogelijk om veel simpeler en goedkoper een airbrush-cabine te bouwen. Het kopen van een cabine was waarschijnlijk beter geweest. Ik gebruikte voor het eerst een kartonnen doos met een ventilator als eerste cabine, wat prima is. Deze cabine was gewoon een leuk projectje voor mij om te maken.
---
Eerst had ik ruimte nodig, in de fietsenstalling onder ons appartement. Na het opruimen had ik een oud schoolbankje gebruikt waar de cabine moest komen.
2024-11-03
![rommel in de stalling](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-03-cleanup)
### Houtbewerking
Eerst had ik stevige planken nodig die als ondergrond zouden dienen. Deze planken had ik nog over van een plantenbak die ik op ons balkon had staan en had afgebroken. Ik had gaatjes geboord, geschuurd en duvels er in gelijmd.
2024-11-06
![duvels en boormachine](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-06-duvels-boormachine)
![fundering lijmen](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-07-fundering-lijmen)
Daarna de zijpanelen en het achterste paneel op maat gezaagd.
2024-11-16
![panelen zagen](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-16-wanden-zagen)
Ik had deze diagonaal gezaagde mastieklatten gebruikt, omdat ik dacht dat ze mooi zouden zijn aan de binnenkant. Ik zou later spijt krijgen dat ik deze latten had gebruikt.
![mastieklat zagen](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-16-mastieklat-zagen)
Een uitsparing aan de bovenkant, zodat de kabels van de verlichting er achter door zouden kunnen.
2024-11-19
![mastieklat uitsparing](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-19-mastieklat-uitsparing)
Het is niet nodig om zoveel duvels te gebruiken, een paar is genoeg. Ik kreeg deze balken niet meer verbonden, omdat sommige duvels niet exact pasten in de tegenovergestelde gaatjes. Ik moest enkel duvels afzagen om het te laten passen.
![veel te veel duvels](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-19-veel-te-veel-duvels)
De mastieklat zagen er mooi uit in de hoeken, maar deze balken waren er lastig om te verlijmen. Ik kreeg de lijmklemmen niet goed, ook niet door een tweede mastieklat als steun te gebruiken. Ze gleden er telkens af en kwamen los. Ik beschouwde dit als een mislukking en heb ze losgemaakt voordat de lijm kon verharden. De resterende lijmresten weggeschuurd en toen besloten om gewone balken te gaan gebruiken voor de hoeken.
2024-11-20
![mastieklat lijmen](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-20-mastieklat-lijmen)
![mastieklat niet egaal](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-20-mastieklat-niet-egaal)
Dit ging veel beter, twee balken op maat gezaagd en wederom een uitsparing gemaakt aan de bovenkant.
2024-11-23
![balken zagen](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-23-balken-zagen)
![uitsparing balk](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-23-balken-uitsparing)
Ik probeerde een balk aan een paneel te lijmen, maar deze paste niet perfect. Enkele duvels waren te lang, dit onderschatte ik tijdens het passen.
2024-11-24
![balk lijmen 1](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-23-balk-lijmen-1)
![balk lijmen 2](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-24-balk-lijmen-2)
![balk lijmen 3](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-24-balk-lijmen-3)
Tijdens het passen, werkt het goed om met een potlood de duvel te markeren. Dan weet je exact hoe diep het tegenovergestelde gat moet zijn.
2024-11-25
![duvel markeren 1](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-25-duvel-aftekenen-1)
![duvel markeren 2](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-25-duvel-aftekenen-2)
Voor de andere hoek wilde ik het wat simpeler doen. Slechts 3 duvels en meteen lijmen. Toen de lijm droog was, de zijkanten schuren. Dit werkte goed, ook voor het achterste paneel.
![balk lijmen 4](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-25-balk-lijmen-4)
![balk lijmen 5](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-25-balk-lijmen-5)
### Schaven
Nu moesten de planken worden voorbereid die de basis zouden vormen voor de hele cabine. Dit waren erg scheluwe, oneven stukken hout en moesten erg veel geschaafd worden om ze (een beetje) recht te krijgen. Ik wilde dit graag zelf doen en deze planken hergebruiken, maar naar een houtwerkplaats gaan om deze planken te laten schaven zou me veel tijd en moeite hebben bespaard. Echter, het is een leuk klusje dat veel voldoening gaf achteraf.
2024-11-27
![schaven 1](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-27-planing-1)
![schaven 3](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-27-planing-3)
Alle wanden vast gelijmd en bovenop de planken geplaatst met een glasplaat. De glasplaat had ik ooit gevonden bij de glascontainer. Het is een dikke plaat zonder schade, waarschijnlijk van een koffietafel geweest.
2024-11-28
![alle wanden](/images/plamo/equipment/workplace/airbrush-cabine/2024-11-28-alle-wanden)
### De deksel
De deksel was gemaakt door 4 kleine blokjes te maken die in de hoeken zouden komen en het frontje zouden vasthouden. Ik was dit keer niet zo zeker dat ik de gaten voor de duvel correct zou kunnen maken, dus heb ik door de blokjes heen geboord en de duvels er doorheen geslagen. Helaas sloeg ik een duvel te hard, die bijna door het frontje breekte. Maar dat was makkelijk te repareren. De deksel zelf wordt niet aan de panelen vastgelijmd, zodat ik deze los kan maken en verplaatsen.
2024-12-07
![deksel blokjes 1](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-07-deksel-blokjes-1)
![deksel blokjes 2](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-07-deksel-blokjes-2)
![de deksel vast lijmen](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-07-deksel-lijmen)
2024-12-08
![airbrush cabine met deksel](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-08-cabine-met-deksel)
Er moeten nu twee grote gaten worden gemaakt in de deksel voor de ventilatie. Ik tekende een cirkel, boorde gaten en hakte de rest eruit met een schietbeitel. Ook hier maakte ik een fout, omdat ik de binnenste diameter van de montagebus gebruikte om te tekenen. Dit had de buitenste moeten zijn.
2024-12-08
![gaten hakken in deksel 1](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-08-deskel-gaten-1)
![gaten hakken in deksel 2](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-08-deskel-gaten-2)
En omdat de montagebus enkele millimeters dik is, paste het niet. Om dit op te lossen, gebruikte ik een rasp om de resterende millimeters weg te halen uit het hout.
2024-12-13
![gaten hakken in deksel 3](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-13-deksel-gaten-3)
![gaten hakken in deksel 4](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-17-deksel-gaten-4)
Nadat beide gaten waren gemaakt, werden alle oneffenheden vlak gemaakt met Alabastine houtplamuur. Daarna kon de eerste onderlaag witte verf er op.
### Verven
Hier zie je de duvel die bijna door het frontje is geslagen. Maar een beetje schuren en plamuur lossen dit snel op en de verf zou alles verbergen.
2024-12-20
![frontje fixen](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-20-frontje-fixen)
Daarna kon het hele werkstuk in de primer.
2024-12-23
![onderlaag verven](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-23-onderlaag-verf)
Na het schuren van de onderlaag en het aanbrengen van een tweede laag, kon ik de witte lak aanbrengen met een verfrollertje. Het is niet nodig, maar het gaf de hele cabine een mooie strakke finish.
2025-01-03
![verfpotten](/images/plamo/equipment/workplace/airbrush-cabine/2024-12-26-verfpotten)
![hele geschilderde cabine](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-03-geverfde-cabine)
### Elektronica
Onze stalling had enkele draden voor verlichting, die ik zou gaan gebruiken voor de elektronica.
2025-01-11
![oude elektronica](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-11-oude-elektronica)
Ik zou de T-splitsing van de ventilatie aan de muur bevestigen met slangenklemmen.
![slangenklemmen aan de muur](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-11-beugels)
De volgende elektronica moest worden bevestigd:
* Een hoofdschakelaar voor de ventilator
* Een schakelaar om de ventilator te laten werken op volle- en halve snelheid.
* Een schakelaar voor de LED-verlichting in de cabine.
* Een omvormer voor gelijkstroom van de LED-verlichting.
* Een dimmer voor de LED-verlichting.
En omdat ik toch bezig was, had ik ook alle verlichting in de stalling vervangen met LED strips, waarbij ik de oude schakelaar kon hergebruiken.n.
Ik wilde in eerste instantie efficiënt zijn met ruimte, door zoveel mogelijk draden in een PVC buis te krijgen. Maar dit was erg lastig om mee te werken en werd uiteindelijk een zooitje. Ik heb alles opnieuw afgebroken om een nieuw plan te proberen.
2025-01-11
![plan A](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-11-plan-A)
Het tweede plan was veel beter, door "modules" (gelabeld 1, 2 en 3) te maken met alle binnenkomende en uitgaande draden. Deze modules komen samen in een lasdoosje in het midden. Dit werkte erg goed, het gaf me de mogelijkheid om elke module apart uit te werken. Het lasdoosje was makkelijk uitbreidbaar, want ik kon nog een extra lijn leggen voor de compressor.
2025-01-15
![plan B](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-15-plan-B)
Alle draden werden geleid door een 5/8 inch PVC buis. Om ze te kunnen buigen, klemde ik een hittepistool vast aan de tafel en gebruikte een speciale buigveer om de buizen met mijn beide te handen kunnen buigen. Dit werkte goed, maar het is alleen mogelijk om draden te leiden door een enkele bocht. Ik maakte in een buis twee bochten, maar kreeg met geen mogelijkheid de lijnen er doorheen. Ik had geen trekveer. Ik moest die buis door midden zagen, de draden er doorheen leiden en weer opnieuw vastmaken.
2025-01-18
![P V C buizen buigen met een hittepistool](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-18-pvc-buigen-hittepistool)
De nieuwe elektronica setup.
2025-01-19
![nieuwe elektronica opstelling](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-19-nieuwe-elektronica)
En toen konden de slangen voor de ventilatie worden bevestigd.
![opstelling met slangen](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-19-nieuwe-setup-met-slangen)
Daarna moesten de LED strips worden gemaakt. Het direct solderen aan de stips was een beetje lastig met alleen mijn handen, dus besloot ik te investeren in een goed setje extra handjes. Ik heb wel eens eerder extra handjes gebruikt, maar deze buigbare klemmen van Weller zijn perfect en maken het solderen een prettig klusje.
2025-01-25
![soldeer apparatuur](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-25-solderen)
Op deze foto zijn de draden nog een beetje kort, dus ik heb die later nog verlengd.
2025-01-31
![L E D strips](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-31-led-strips)
Ik dacht dat het handig zou zijn al ik een extra stopcontact zou hebben bij de vloer voor de compressor, waarbij ik makkelijk bij de schakelaar zou kunnen. Het lasdoosje was net groot genoeg voor al deze connecties.
![extra lijn voor de compressor](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-31-compressor-lijn)
![lasdoosje](/images/plamo/equipment/workplace/airbrush-cabine/2025-01-31-lasdoosje)
### Afronding
Ik maakte de vier LED strips vast, aan elke zijde van de deksel. Het eindresultaat is een mooie doos met daglicht gekleurd licht van elke hoek.
2025-02-09
![laatste stap](/images/plamo/equipment/workplace/airbrush-cabine/2025-02-09-final-light-setup)
Een vriend van me zei dat het een beetje op een hangar leek, hier is een 1/144 Zaku II voor schaal.
![zaku hangar](/images/plamo/equipment/workplace/airbrush-cabine/2025-02-09-zaku-hangar)
Nu dat alles compleet is en geïnspireerd door de hangar opmerking, besloot ik om mijn cabine de naam: ["White Base"](https://en.wikipedia.org/wiki/White_Base) te geven.

View File

@ -0,0 +1,9 @@
# Plamo
Het bouwen en schilderen van plastic schaalmodellen en mecha figuren is een hobby van me. Hier is een collectie van de dingen die I heb gemaakt en gebruik.
---
### Gereedschappen
* [Airbrush cabine](./equipment/airbrush-cabine)

View File

@ -1,26 +0,0 @@
### Gundam wishlist:
* MG MSM-07 Zgok
* HG AGX-04 Gerbera Tetra
* HG MSJ-06II-A Tieren Ground Type
* Bandai - BPHD-38 ms hand 02 (Zeon)
---
### Equipment wishlist:
* Dremel, Proxxon
* Bluetack
* Kruidvat nagellak verwijderaar (met of zonder aceton)
* UV light for curing
---
### Diorama wishlist:
* XPS insulation foam
* Hot wire cutter
* LED filament lines
* UV resin

View File

@ -4,53 +4,44 @@ import React from 'react';
const AttachmentModule = () => {
return (
<div className='row'>
<div className="sidebar col-3 position-fixed">
<div id="list-example" className="list-group">
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-intro">intro</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-workflow">workflow</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-lessons-learnt">lessons learnt</a>
</div>
</div>
<a href='..'>Software</a>
<section id="list-intro" className="content-section">
<h1 className="text-primary">Attachment Module</h1>
<h4 className="text-secondary">Solving the problem of someone else</h4>
<p>Sometimes a project owner wants a feature implemented in their project that the developers somehow are unable to realize. The project was a website containing a form that customers would enter text data on. The project owner asked for a feature which allowed customers to attach files to this form.</p>
<p>As a "temporary" solution, I suggested creating a stand-alone server that would handle file uploads that would be linked to the ID number of the form. This consisted of 2 servers. One server would be a simple web interface, the other a database server that hosted a simple API.</p>
<p>Both servers were VMs running <a href="https://en.wikipedia.org/wiki/Red_Hat_Enterprise_Linux" target="_blank" rel="noopener noreferrer">RHEL</a>.</p>
<p>The web server used the <a href="https://en.wikipedia.org/wiki/Nginx" target="_blank" rel="noopener noreferrer">Nginx</a> engine and the <a href="https://en.wikipedia.org/wiki/Django_(web_framework)" target="_blank" rel="noopener noreferrer">Django</a> framework. Python handles the HTTP requests with <a href="https://en.wikipedia.org/wiki/Gunicorn" target="_blank" rel="noopener noreferrer">Gunicorn</a>, a <a href="https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface" target="_blank" rel="noopener noreferrer">WSGI</a> gateway.</p>
<p>The database server used a <a href="https://en.wikipedia.org/wiki/MySQL" target="_blank" rel="noopener noreferrer">MySQL</a> server to host uploaded file data. To expose this data, <a href="https://flask-restful.readthedocs.io/" target="_blank" rel="noopener noreferrer">Flask RESTful</a> was used to serve a simple API.</p>
<p>This was the first separate project I created for the company, so I set up a <a href="https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface" target="_blank" rel="noopener noreferrer">GitLab</a> server for version control.</p>
</section>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-intro" className="content-section">
<h1 className="text-primary">Attachment Module</h1>
<h4 className="text-secondary">Solving the problem of someone else</h4>
<p>Sometimes a project owner wants a feature implemented in their project that the developers somehow are unable to realize. The project was a website containing a form that customers would enter text data on. The project owner asked for a feature which allowed customers to attach files to this form.</p>
<p>As a "temporary" solution, I suggested creating a stand-alone server that would handle file uploads that would be linked to the ID number of the form. This consisted of 2 servers. One server would be a simple web interface, the other a database server that hosted a simple API.</p>
<p>Both servers were VMs running <a href="https://en.wikipedia.org/wiki/Red_Hat_Enterprise_Linux" target="_blank" rel="noopener noreferrer">RHEL</a>.</p>
<p>The web server used the <a href="https://en.wikipedia.org/wiki/Nginx" target="_blank" rel="noopener noreferrer">Nginx</a> engine and the <a href="https://en.wikipedia.org/wiki/Django_(web_framework)" target="_blank" rel="noopener noreferrer">Django</a> framework. Python handles the HTTP requests with <a href="https://en.wikipedia.org/wiki/Gunicorn" target="_blank" rel="noopener noreferrer">Gunicorn</a>, a <a href="https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface" target="_blank" rel="noopener noreferrer">WSGI</a> gateway.</p>
<p>The database server used a <a href="https://en.wikipedia.org/wiki/MySQL" target="_blank" rel="noopener noreferrer">MySQL</a> server to host uploaded file data. To expose this data, <a href="https://flask-restful.readthedocs.io/" target="_blank" rel="noopener noreferrer">Flask RESTful</a> was used to serve a simple API.</p>
<p>This was the first separate project I created for the company, so I set up a <a href="https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface" target="_blank" rel="noopener noreferrer">GitLab</a> server for version control.</p>
</section>
<section id="list-workflow" className="content-section">
<h2 className="text-primary">Workflow</h2>
<ol>
<li>The website hosting the forms, would serve a hyperlink to the "attachment module", along with the form's ID.</li>
<li>The user is redirected to the website with a simple input field and browse button where a file can be uploaded.</li>
<li>The file is validated by type, size and upload time.</li>
<li>The file is copied to the database server.</li>
<li>The file is also cached for 2 weeks on the web server, for quicker access.</li>
<li>The database server creates a database entry.</li>
<li>A link to the file is created for access on the website.</li>
</ol>
<p>After a file is uploaded, someone else will want to access it.</p>
<ol>
<li>The user accesses the website and clicks on the link with the file name.</li>
<li>If the file is cached on the web server, then this file is opened.</li>
<li>If the file is not cached, the web server downloads the file from the database server and then opens it.</li>
<section id="list-workflow" className="content-section">
<h2 className="text-primary">Workflow</h2>
<ol>
<li>The website hosting the forms, would serve a hyperlink to the "attachment module", along with the form's ID.</li>
<li>The user is redirected to the website with a simple input field and browse button where a file can be uploaded.</li>
<li>The file is validated by type, size and upload time.</li>
<li>The file is copied to the database server.</li>
<li>The file is also cached for 2 weeks on the web server, for quicker access.</li>
<li>The database server creates a database entry.</li>
<li>A link to the file is created for access on the website.</li>
</ol>
</section>
<p>After a file is uploaded, someone else will want to access it.</p>
<ol>
<li>The user accesses the website and clicks on the link with the file name.</li>
<li>If the file is cached on the web server, then this file is opened.</li>
<li>If the file is not cached, the web server downloads the file from the database server and then opens it.</li>
</ol>
</section>
<section id="list-lessons-learnt" className="content-section">
<h2 className="text-primary">Lessons learnt</h2>
<p>The project owner did not want the users to separately log in to the web server of the attachment module. So a big security issue is that anyone with the link, can access uploaded files. At the time this was agreed to be a <i>temporary</i> solution. The project was deployed in 2017 and in 2021 this project was still running though. After all, the business must go on and if the problem's symptoms seems fixed, why bother with it further...</p>
<p>Because other users could access other uploaded files using the right link, it was decided that users could only upload and never delete any files.</p>
<p>A big learning point for me was that not to compromise security, even for projects that are considered temporary. A problem never occurred. This compromise caused silly decisions to not allow users to delete their own files. I will defend my standpoint much more and use this project as an example.</p>
<p>The actual problem here though, is why the other developers were not able to create a safe file upload feature.</p>
</section>
</div>
<section id="list-lessons-learnt" className="content-section">
<h2 className="text-primary">Lessons learnt</h2>
<p>The project owner did not want the users to separately log in to the web server of the attachment module. So a big security issue is that anyone with the link, can access uploaded files. At the time this was agreed to be a <i>temporary</i> solution. The project was deployed in 2017 and in 2021 this project was still running though. After all, the business must go on and if the problem's symptoms seems fixed, why bother with it further...</p>
<p>Because other users could access other uploaded files using the right link, it was decided that users could only upload and never delete any files.</p>
<p>A big learning point for me was that not to compromise security, even for projects that are considered temporary. A problem never occurred. This compromise caused silly decisions to not allow users to delete their own files. I will defend my standpoint much more and use this project as an example.</p>
<p>The actual problem here though, is why the other developers were not able to create a safe file upload feature.</p>
</section>
</div>
)
}

View File

@ -4,60 +4,58 @@ import React from 'react';
const BoardOfEducationBot = () => {
return (
<div className='row'>
<a href='..'>Software</a>
<section id="list-intro" className="content-section">
<h1 className="text-primary">Board of Education bot</h1>
<h4 className="text-secondary">Learning robot platform</h4>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-intro" className="content-section">
<h1 className="text-primary">Board of Education bot</h1>
<h4 className="text-secondary">Learning robot platform</h4>
<p>The Board of education Robot is a development platform made by Parallax.</p>
<p>This school project was mainly to learn about basic electronics and programming for embedded devices. The BoeBot was created by Parallax and uses the Javelin stamp processor. This processor accepts the high-level programming language Java to control different pieces of hardware on the robot. The robot started as a simple prototype board with two servo motors. Sensors and actuators were later placed on the breadboard to allow sensory input and output. We created a GUI named "Robot at Work" which allowed the robot to follow a path using QPI linefollowers. The robot could also be controlled with an IR remote control.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_classdiagram-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_classdiagram-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_classdiagram-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_classdiagram.webp`} />
<img alt="Class diagram" src={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_classdiagram.webp`}/>
</picture>
<p>The Board of education Robot is a development platform made by Parallax.</p>
<p>This school project was mainly to learn about basic electronics and programming for embedded devices. The BoeBot was created by Parallax and uses the Javelin stamp processor. This processor accepts the high-level programming language Java to control different pieces of hardware on the robot. The robot started as a simple prototype board with two servo motors. Sensors and actuators were later placed on the breadboard to allow sensory input and output. We created a GUI named "Robot at Work" which allowed the robot to follow a path using QPI linefollowers. The robot could also be controlled with an IR remote control.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_classdiagram-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_classdiagram-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_classdiagram-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_classdiagram.webp`} />
<img alt="Class diagram" src={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_classdiagram.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_gui-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_gui-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_gui.webp`} />
<img alt="G U I for this project" src={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_gui.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_gui-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_gui-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_gui.webp`} />
<img alt="G U I for this project" src={`${process.env.PUBLIC_URL}/images/projects/boebot/boebot_gui.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/robot2-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/robot2-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/robot2.webp`} />
<img alt="B O E bot" src={`${process.env.PUBLIC_URL}/images/projects/boebot/robot2.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/robot2-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/robot2-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/robot2.webp`} />
<img alt="B O E bot" src={`${process.env.PUBLIC_URL}/images/projects/boebot/robot2.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/robot3-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/robot3-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/robot3.webp`} />
<img alt="B O E bot" src={`${process.env.PUBLIC_URL}/images/projects/boebot/robot3.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/robot3-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/robot3-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/robot3.webp`} />
<img alt="B O E bot" src={`${process.env.PUBLIC_URL}/images/projects/boebot/robot3.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/javelin-w240.webp`} />
<source media="(min-width: 800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/javelin.webp`} />
<img alt="Javelin chip" src={`${process.env.PUBLIC_URL}/images/projects/boebot/javelin.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/javelin-w240.webp`} />
<source media="(min-width: 800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/boebot/javelin.webp`} />
<img alt="Javelin chip" src={`${process.env.PUBLIC_URL}/images/projects/boebot/javelin.webp`}/>
</picture>
</section>
</div>
</section>
</div>
)
}

View File

@ -4,93 +4,82 @@ import React from 'react';
const ConfigAutomation = () => {
return (
<div className='row'>
<div className="sidebar col-3 position-fixed">
<div id="list-example" className="list-group">
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-config-automation">Config automation</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-development">Development</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-deployment">Deployment</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-feedback">Feedback</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-lessons-learnt">Lessons learnt</a>
</div>
</div>
<a href='..'>Software</a>
<section id="list-config-automation" className="content-section">
<h1 className="text-primary">Configuration automation</h1>
<p>At <a href="https://www.hitachivantara.com/" target="_blank" rel="noopener noreferrer">Hitachi Vantara</a> I worked with other developers on automating a configuration process using <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer">Python</a> and several external API.</p>
<p>Products would be picked, assembled, configured and finally packaged for shipping at the distribution centre where I collaborated on this project. Configuration happend by connecting a Windows laptop to the product and apply settings. This related to the product's operating system, network and storage settings.</p>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-config-automation" className="content-section">
<h1 className="text-primary">Configuration automation</h1>
<p>At <a href="https://www.hitachivantara.com/" target="_blank" rel="noopener noreferrer">Hitachi Vantara</a> I worked with other developers on automating a configuration process using <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer">Python</a> and several external API.</p>
<p>Products would be picked, assembled, configured and finally packaged for shipping at the distribution centre where I collaborated on this project. Configuration happend by connecting a Windows laptop to the product and apply settings. This related to the product's operating system, network and storage settings.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-config-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-config-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-config-w800.webp`} />
<img alt="CTO configuration" src={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-config-w800.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-config-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-config-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-config-w800.webp`} />
<img alt="CTO configuration" src={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-config-w800.webp`}/>
</picture>
</section>
</section>
<section id="list-development" className="content-section">
<h2 className="text-primary">Development</h2>
<p>This project started as a local Python 2 script when it started, to only automate very specific settings. It later moved to USB drives and eventually to a VM on a network.</p>
<p>It eventually grew to support multiple product lines and at this moment I joined the other programmer to further extend this software after my internship.</p>
<p>Here I learnt working properly with Git and designing software architecture. I also learnt how to create automation by interfacing by GUI automation with <a href="https://www.autohotkey.com/" target="_blank" rel="noopener noreferrer">AutoHotkey</a> and combine multiple APIs to achieve results.</p>
<p>The automation software also used other resources like <a href="https://ttssh2.osdn.jp/index.html.en" target="_blank" rel="noopener noreferrer">Tera Term</a> scripts.</p>
<p>Another fun thing I added was an <a href="https://www.raritan.com/products/power/power-distribution" target="_blank" rel="noopener noreferrer">iPDU</a> where Python could safely powercycle 230 Volt AC power consumers. This was useful to power down devices when the distribution center was not operating at night to reduce costs.</p>
<section id="list-development" className="content-section">
<h2 className="text-primary">Development</h2>
<p>This project started as a local Python 2 script when it started, to only automate very specific settings. It later moved to USB drives and eventually to a VM on a network.</p>
<p>It eventually grew to support multiple product lines and at this moment I joined the other programmer to further extend this software after my internship.</p>
<p>Here I learnt working properly with Git and designing software architecture. I also learnt how to create automation by interfacing by GUI automation with <a href="https://www.autohotkey.com/" target="_blank" rel="noopener noreferrer">AutoHotkey</a> and combine multiple APIs to achieve results.</p>
<p>The automation software also used other resources like <a href="https://ttssh2.osdn.jp/index.html.en" target="_blank" rel="noopener noreferrer">Tera Term</a> scripts.</p>
<p>Another fun thing I added was an <a href="https://www.raritan.com/products/power/power-distribution" target="_blank" rel="noopener noreferrer">iPDU</a> where Python could safely powercycle 230 Volt AC power consumers. This was useful to power down devices when the distribution center was not operating at night to reduce costs.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-laptop-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-laptop-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-laptop-w800.webp`} />
<img alt="CTO laptop" src={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-laptop-w800.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-laptop-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-laptop-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-laptop-w800.webp`} />
<img alt="CTO laptop" src={`${process.env.PUBLIC_URL}/images/projects/hitachi/cto-laptop-w800.webp`}/>
</picture>
</section>
</section>
<section id="list-deployment" className="content-section">
<h2 className="text-primary">Deployment</h2>
<p>Creating the release of this software had to be done by running a batch script to create a bundled set of Python files. These files were then uploaded to the VM located in a European distribution center in the Netherlands. This VM is then used to run the software from on a local network on which all configuration laptops were connected to. A WinSCP script would then sync the contents of all VM's in distribution centres located in Singapore, United States and China in 24 hours.</p>
<p>A script (stub) on the configuration laptop would connect to the VM and run Python locally to receive instructions. The technician selects the product through a CLI menu and automated configuration starts.</p>
<p>Dedicated storage managing software had to be installed, so communicating with the Japanese supplier was always important. This software and other assets were separately deployed to create a stable configuration process.</p>
<section id="list-deployment" className="content-section">
<h2 className="text-primary">Deployment</h2>
<p>Creating the release of this software had to be done by running a batch script to create a bundled set of Python files. These files were then uploaded to the VM located in a European distribution center in the Netherlands. This VM is then used to run the software from on a local network on which all configuration laptops were connected to. A WinSCP script would then sync the contents of all VM's in distribution centres located in Singapore, United States and China in 24 hours.</p>
<p>A script (stub) on the configuration laptop would connect to the VM and run Python locally to receive instructions. The technician selects the product through a CLI menu and automated configuration starts.</p>
<p>Dedicated storage managing software had to be installed, so communicating with the Japanese supplier was always important. This software and other assets were separately deployed to create a stable configuration process.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/storage-chassis-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/storage-chassis-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/storage-chassis-w800.webp`} />
<img alt="Hitachi Storage Chassis" src={`${process.env.PUBLIC_URL}/images/projects/hitachi/storage-chassis-w800.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/storage-chassis-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/storage-chassis-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/storage-chassis-w800.webp`} />
<img alt="Hitachi Storage Chassis" src={`${process.env.PUBLIC_URL}/images/projects/hitachi/storage-chassis-w800.webp`}/>
</picture>
</section>
</section>
<section id="list-feedback" className="content-section">
<h2 className="text-primary">Feedback</h2>
<p>The application generated log files with each configuration and then upload these back to the VM after configuration was complete or halted. These logs were sorted under product name and the order number. But quite often, I found it very productive to go to the configuration area and simply talk with the technician to figure out what went wrong. Depending on the severity of the problem, it would get documented in Gitlab issues. On a weekly basis, issues would get assigned among developers.</p>
<p>Communication is always important and essential for proper DevOps. The people who operate and configure these machines daily often know a lot more details that can be used to optimize the software. But be certain to make them realize that they also contribute to profit, rather than believing their job may become obsolete.</p>
<section id="list-feedback" className="content-section">
<h2 className="text-primary">Feedback</h2>
<p>The application generated log files with each configuration and then upload these back to the VM after configuration was complete or halted. These logs were sorted under product name and the order number. But quite often, I found it very productive to go to the configuration area and simply talk with the technician to figure out what went wrong. Depending on the severity of the problem, it would get documented in Gitlab issues. On a weekly basis, issues would get assigned among developers.</p>
<p>Communication is always important and essential for proper DevOps. The people who operate and configure these machines daily often know a lot more details that can be used to optimize the software. But be certain to make them realize that they also contribute to profit, rather than believing their job may become obsolete.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/hitachi-banner-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/hitachi-banner-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/hitachi-banner-w800.webp`} />
<img alt="Hitachi HiCEF banner" src={`${process.env.PUBLIC_URL}/images/projects/hitachi/hitachi-banner-w800.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/hitachi-banner-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/hitachi-banner-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/hitachi-banner-w800.webp`} />
<img alt="Hitachi HiCEF banner" src={`${process.env.PUBLIC_URL}/images/projects/hitachi/hitachi-banner-w800.webp`}/>
</picture>
</section>
</section>
<section id="list-lessons-learnt" className="content-section">
<h2 className="text-primary">Lessons learnt</h2>
<p>Being a programmer, I was mostly concerned with the software. But it requires hardware to run on. When the software does not work because of differences in the platform the software run on, what is there to do? I eventually started managing around 40 configuration laptops, using <a href="https://clonezilla.org/" target="_blank" rel="noopener noreferrer">Clonezilla</a> to create identical machines.</p>
<p>Docker would have been an ideal solution, but I did not know much of it at the time.</p>
<p>Also my many points of learning in git merges, creating release tags, deploying broken versions of the software and immediately needing to patch with hotfixes, all contributed to my learning of software development.</p>
<p>Automation demands an equalized platform to run on and once it is deployed, hundreds of products will be making use of it. So, thinking something over and propely design and architecture software is much more time-saving than quickly meeting deadlines.</p>
<section id="list-lessons-learnt" className="content-section">
<h2 className="text-primary">Lessons learnt</h2>
<p>Being a programmer, I was mostly concerned with the software. But it requires hardware to run on. When the software does not work because of differences in the platform the software run on, what is there to do? I eventually started managing around 40 configuration laptops, using <a href="https://clonezilla.org/" target="_blank" rel="noopener noreferrer">Clonezilla</a> to create identical machines.</p>
<p>Docker would have been an ideal solution, but I did not know much of it at the time.</p>
<p>Also my many points of learning in git merges, creating release tags, deploying broken versions of the software and immediately needing to patch with hotfixes, all contributed to my learning of software development.</p>
<p>Automation demands an equalized platform to run on and once it is deployed, hundreds of products will be making use of it. So, thinking something over and propely design and architecture software is much more time-saving than quickly meeting deadlines.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/many-laptops-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/many-laptops-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/many-laptops-w800.webp`} />
<img alt="Many laptops" src={`${process.env.PUBLIC_URL}/images/projects/hitachi/many-laptops-w800.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/many-laptops-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/many-laptops-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/hitachi/many-laptops-w800.webp`} />
<img alt="Many laptops" src={`${process.env.PUBLIC_URL}/images/projects/hitachi/many-laptops-w800.webp`}/>
</picture>
</section>
</div>
</section>
</div>
)
}

View File

@ -4,40 +4,30 @@ import React from 'react';
const DXPDevelopment = () => {
return (
<div className='row'>
<div className="sidebar col-3 position-fixed">
<div id="list-example" className="list-group">
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-dxp">DXP</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-legacy">Legacy</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-improvement">Improvement</a>
</div>
</div>
<a href='..'>Software</a>
<section id="list-dxp" className="content-section">
<h1 className="text-primary">DXP Development</h1>
<h4 className="text-secondary">OPPLE Catalog Generator</h4>
<p>What is DXP? It stands for Digital Experience Platform and is basically interactive software where data can be maintained. One such DXP I loved working on was for <a href="https://www.opple.eu/" target="_blank" rel="noopener noreferrer">OPPLE</a>. They are a brand of lighting products and have over 14000 different items.</p>
<p>My contributions were taking ownership of their catalog generator tool and maintaining the data of their products in <a href="https://www.drupal.org/" target="_blank" rel="noopener noreferrer">Drupal</a> on their website.</p>
<p>You can view the catalog here: <a href="https://www.opple.nl/en/product-catalogue-np" target="_blank" rel="noopener noreferrer">https://www.opple.nl/en/product-catalogue-np</a></p>
<p>All the data was supplied through an external API by <a href="https://www.compano.com/" target="_blank" rel="noopener noreferrer">Compano</a> and through an uploaded XML file. This data had to be parsed and converged into a logical structure so that products and product families were matched along with their features, photographs, accessoires, dimensional drawings, sensor diagrams and more. And all data is <a href="https://en.wikipedia.org/wiki/Multilingualism" target="_blank" rel="noopener noreferrer">multilingual</a>. And of course data had to be exchanged through excel files for pricelists and tender texts. Data was used interchangably between different tools and websites.</p>
<img src={`${process.env.PUBLIC_URL}/images/projects/opple/opple-catalog.webp`} alt="opple catalog"/>
<p>The catalog generator makes use of the Drupal platform as an intranet portal where thousands of PDF's could be automatically generated in a single batch. The customer only has to alter the data and the layouts and appropriate sections appear.</p>
</section>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-dxp" className="content-section">
<h1 className="text-primary">DXP Development</h1>
<h4 className="text-secondary">OPPLE Catalog Generator</h4>
<p>What is DXP? It stands for Digital Experience Platform and is basically interactive software where data can be maintained. One such DXP I loved working on was for <a href="https://www.opple.eu/" target="_blank" rel="noopener noreferrer">OPPLE</a>. They are a brand of lighting products and have over 14000 different items.</p>
<p>My contributions were taking ownership of their catalog generator tool and maintaining the data of their products in <a href="https://www.drupal.org/" target="_blank" rel="noopener noreferrer">Drupal</a> on their website.</p>
<p>You can view the catalog here: <a href="https://www.opple.nl/en/product-catalogue-np" target="_blank" rel="noopener noreferrer">https://www.opple.nl/en/product-catalogue-np</a></p>
<p>All the data was supplied through an external API by <a href="https://www.compano.com/" target="_blank" rel="noopener noreferrer">Compano</a> and through an uploaded XML file. This data had to be parsed and converged into a logical structure so that products and product families were matched along with their features, photographs, accessoires, dimensional drawings, sensor diagrams and more. And all data is <a href="https://en.wikipedia.org/wiki/Multilingualism" target="_blank" rel="noopener noreferrer">multilingual</a>. And of course data had to be exchanged through excel files for pricelists and tender texts. Data was used interchangably between different tools and websites.</p>
<img src={`${process.env.PUBLIC_URL}/images/projects/opple/opple-catalog.webp`} alt="opple catalog"/>
<p>The catalog generator makes use of the Drupal platform as an intranet portal where thousands of PDF's could be automatically generated in a single batch. The customer only has to alter the data and the layouts and appropriate sections appear.</p>
</section>
<section id="list-legacy" className="content-section">
<h3 className="text-primary">Legacy</h3>
<p>This project was handed to me as a <a href="https://en.wikipedia.org/wiki/Monolithic_application" target="_blank" rel="noopener noreferrer">monolithic source</a>, with only 1 PHP file containing all the rendering logic and handling exceptions (as in, many products had their own unique, exceptional attributes). This was a project that had outgrown itself and was hard to scale further due to the current structure. I had to improve the code base, while retaining the legacy functions. But because everything was so tightly coupled I had to make sure a change did not break functionality elsewhere. The key is to write new code and provide "safety nets" for older code.</p>
<p>A common misconception is to think by creating quick code, is easy gain. Not much effort, just copy and paste the existing logic and adjust it a bit. Then put it in the same file, no need to document it. But by building up <a href="https://en.wikipedia.org/wiki/Technical_debt" target="_blank" rel="noopener noreferrer">Technical Dept</a>, you will either leave this code behind or you will forget how everything works. Making code scalable, is essential. Even for "small" or "temporary" projects. Do not take shortcuts, thinking it will save time or meet the deadline.</p>
</section>
<section id="list-improvement" className="content-section">
<h3 className="text-primary">Improvement</h3>
<p>Restructuring code built as such requires mostly patience. You cannot instantly restart everything, as this tool is used in production. You cannot create a new architecture complete with diagrams, there is currently no time. It is not the only project I work on, there are 20 other projects that also require attention. Instead, I started by moving functions around every time I worked on a new feature for the tool. Dedicating existing functions to separate module files was the start. Creating object-oriented code for new features was the next step. Applying unit tests came next. As long as a new feature request did not exceed in time, it could be slowly prepared to grow by having prework done every time.</p>
<p>Eventually, it became a tool with composed logic, making future maintenance and feature requests a lot more simple.</p>
<p>Moving forward with a structured tool, I am proud to have collaborated on this project!</p>
</section>
</div>
<section id="list-legacy" className="content-section">
<h3 className="text-primary">Legacy</h3>
<p>This project was handed to me as a <a href="https://en.wikipedia.org/wiki/Monolithic_application" target="_blank" rel="noopener noreferrer">monolithic source</a>, with only 1 PHP file containing all the rendering logic and handling exceptions (as in, many products had their own unique, exceptional attributes). This was a project that had outgrown itself and was hard to scale further due to the current structure. I had to improve the code base, while retaining the legacy functions. But because everything was so tightly coupled I had to make sure a change did not break functionality elsewhere. The key is to write new code and provide "safety nets" for older code.</p>
<p>A common misconception is to think by creating quick code, is easy gain. Not much effort, just copy and paste the existing logic and adjust it a bit. Then put it in the same file, no need to document it. But by building up <a href="https://en.wikipedia.org/wiki/Technical_debt" target="_blank" rel="noopener noreferrer">Technical Dept</a>, you will either leave this code behind or you will forget how everything works. Making code scalable, is essential. Even for "small" or "temporary" projects. Do not take shortcuts, thinking it will save time or meet the deadline.</p>
</section>
<section id="list-improvement" className="content-section">
<h3 className="text-primary">Improvement</h3>
<p>Restructuring code built as such requires mostly patience. You cannot instantly restart everything, as this tool is used in production. You cannot create a new architecture complete with diagrams, there is currently no time. It is not the only project I work on, there are 20 other projects that also require attention. Instead, I started by moving functions around every time I worked on a new feature for the tool. Dedicating existing functions to separate module files was the start. Creating object-oriented code for new features was the next step. Applying unit tests came next. As long as a new feature request did not exceed in time, it could be slowly prepared to grow by having prework done every time.</p>
<p>Eventually, it became a tool with composed logic, making future maintenance and feature requests a lot more simple.</p>
<p>Moving forward with a structured tool, I am proud to have collaborated on this project!</p>
</section>
</div>
)
}

View File

@ -4,52 +4,43 @@ import React from 'react';
const EmbeddedInternetRadio = () => {
return (
<div className='row'>
<div className="sidebar col-3 position-fixed">
<div id="list-example" className="list-group">
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-intro">Intro</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-development">Development</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-design">Design</a>
</div>
</div>
<a href='..'>Software</a>
<section id="list-intro" className="content-section">
<h1 className="text-primary">Embedded Internet Radio</h1>
<h4 className="text-secondary">Working with C</h4>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-intro" className="content-section">
<h1 className="text-primary">Embedded Internet Radio</h1>
<h4 className="text-secondary">Working with C</h4>
<p>This project gave me the opportunity to work with the SIR120 internet radio made by the company StreamIT. The radio involved connecting to exiting internet streams and interfacing with the <a href="https://en.wikipedia.org/wiki/Liquid-crystal_display" target="_blank" rel="noopener noreferrer">LCD</a> and buttons on the device. The code was written in <a href="https://en.wikipedia.org/wiki/C_(programming_language)" target="_blank" rel="noopener noreferrer">C</a>.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/front-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/front-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/front.webp`} />
<img alt="Stream I T front of radio" src={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/front.webp`}/>
</picture>
</section>
<p>This project gave me the opportunity to work with the SIR120 internet radio made by the company StreamIT. The radio involved connecting to exiting internet streams and interfacing with the <a href="https://en.wikipedia.org/wiki/Liquid-crystal_display" target="_blank" rel="noopener noreferrer">LCD</a> and buttons on the device. The code was written in <a href="https://en.wikipedia.org/wiki/C_(programming_language)" target="_blank" rel="noopener noreferrer">C</a>.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/front-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/front-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/front.webp`} />
<img alt="Stream I T front of radio" src={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/front.webp`}/>
</picture>
</section>
<section id="list-development" className="content-section">
<h2 className="text-primary">Development</h2>
<p>The radio had an existing operating system called <a href="https://en.wikipedia.org/wiki/Ethernut" target="_blank" rel="noopener noreferrer">Nut/OS</a>, an open source OS. Nut/OS provided the TCP/IP stack we required to connect the device to the internet. The radio was able to play a select number of internet streams. The user could read the stream channel on the LCD and use the buttons to navigate between them.</p>
<p>This project often had code overhauls because our code kept moving towards a more <a href="https://en.wikipedia.org/wiki/Object-oriented_programming" target="_blank" rel="noopener noreferrer">OOP</a> approach using structs rather than large chunks of produral code.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/inside-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/inside-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/inside.webp`} />
<img alt="Stream I T inside of the radio" src={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/inside.webp`}/>
</picture>
</section>
<section id="list-development" className="content-section">
<h2 className="text-primary">Development</h2>
<p>The radio had an existing operating system called <a href="https://en.wikipedia.org/wiki/Ethernut" target="_blank" rel="noopener noreferrer">Nut/OS</a>, an open source OS. Nut/OS provided the TCP/IP stack we required to connect the device to the internet. The radio was able to play a select number of internet streams. The user could read the stream channel on the LCD and use the buttons to navigate between them.</p>
<p>This project often had code overhauls because our code kept moving towards a more <a href="https://en.wikipedia.org/wiki/Object-oriented_programming" target="_blank" rel="noopener noreferrer">OOP</a> approach using structs rather than large chunks of produral code.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/inside-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/inside-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/inside.webp`} />
<img alt="Stream I T inside of the radio" src={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/inside.webp`}/>
</picture>
</section>
<section id="list-design" className="content-section">
<h2 className="text-primary">Design</h2>
<p>A simple flowchart was created to show how the user could navigate through the menu.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/flowchart-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/flowchart-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/flowchart-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/flowchart.webp`} />
<img alt="Program flow chart" src={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/flowchart.webp`}/>
</picture>
</section>
</div>
<section id="list-design" className="content-section">
<h2 className="text-primary">Design</h2>
<p>A simple flowchart was created to show how the user could navigate through the menu.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/flowchart-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/flowchart-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/flowchart-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/flowchart.webp`} />
<img alt="Program flow chart" src={`${process.env.PUBLIC_URL}/images/projects/embedded-internet-radio/flowchart.webp`}/>
</picture>
</section>
</div>
)
}

View File

@ -4,86 +4,84 @@ import React from 'react';
const FestivalSimulator = () => {
return (
<div className='row'>
<a href='..'>Software</a>
<section id="list-intro" className="content-section">
<h1 className="text-primary">SimFest Tycoon</h1>
<h4 className="text-secondary">Festival crowd simulator</h4>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-intro" className="content-section">
<h1 className="text-primary">SimFest Tycoon</h1>
<h4 className="text-secondary">Festival crowd simulator</h4>
<p>A team project in which a festival can be simulated to view how crowds of people behave. The user can build festivals, roads, snackbars and assign time periods when a band plays at a stage. The project was programmed in Java. A school project made by four people. The software allows users to build their own festival grounds. Snackbarstands, toilets, roads and stages can be placed to view how people form crowds and bottlenecks in certain areas. The user can also assign a band that plays for a certain time at a stage using a scheduler. </p>
<p>The band has a timeperiod and popularity, which affects the amount of people visiting that stage. The goal of this software is create an overview of potential bottlenecks and overcrowded areas.</p>
<p>A team project in which a festival can be simulated to view how crowds of people behave. The user can build festivals, roads, snackbars and assign time periods when a band plays at a stage. The project was programmed in Java. A school project made by four people. The software allows users to build their own festival grounds. Snackbarstands, toilets, roads and stages can be placed to view how people form crowds and bottlenecks in certain areas. The user can also assign a band that plays for a certain time at a stage using a scheduler. </p>
<p>The band has a timeperiod and popularity, which affects the amount of people visiting that stage. The goal of this software is create an overview of potential bottlenecks and overcrowded areas.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft2-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft2-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft2-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft2.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft2.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft2-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft2-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft2-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft2.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft2.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft4-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft4-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft4-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft4.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft4.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft4-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft4-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft4-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft4.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft4.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft5-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft5-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft5-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft5.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft5.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft5-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft5-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft5-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft5.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft5.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft7-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft7-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft7-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft7.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft7.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft7-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft7-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft7-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft7.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft7.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft8-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft8-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft8-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft8.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft8.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft8-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft8-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft8-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft8.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft8.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft9-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft9-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft9-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft9.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft9.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft9-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft9-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft9-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft9.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft9.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft10-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft10-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft10-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft10.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft10.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft10-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft10-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft10-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft10.webp`} />
<img alt="Screenshot festival simulator" src={`${process.env.PUBLIC_URL}/images/projects/festival-simulator/sft10.webp`}/>
</picture>
</section>
</div>
</section>
</div>
)
}

View File

@ -4,37 +4,35 @@ import React from 'react';
const IOSAirports = () => {
return (
<div className='row'>
<a href='..'>Software</a>
<section id="list-intro" className="content-section">
<h1 className="text-primary">iOS Airports</h1>
<h4 className="text-secondary">iPhone application</h4>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-intro" className="content-section">
<h1 className="text-primary">iOS Airports</h1>
<h4 className="text-secondary">iPhone application</h4>
<p>A mobile iPhone application using a <a href="https://sqlite.org/" target="_blank" rel="noopener noreferrer">SQLite</a> database to display airports around the world. With this project I got to experience working with <a href="https://en.wikipedia.org/wiki/Xcode" target="_blank" rel="noopener noreferrer">Xcode</a> and <a href="https://en.wikipedia.org/wiki/Swift_(programming_language)" target="_blank" rel="noopener noreferrer">Swift</a> to develop iOS mobile applications.</p>
<p>A mobile iPhone application using a <a href="https://sqlite.org/" target="_blank" rel="noopener noreferrer">SQLite</a> database to display airports around the world. With this project I got to experience working with <a href="https://en.wikipedia.org/wiki/Xcode" target="_blank" rel="noopener noreferrer">Xcode</a> and <a href="https://en.wikipedia.org/wiki/Swift_(programming_language)" target="_blank" rel="noopener noreferrer">Swift</a> to develop iOS mobile applications.</p>
<p>
Source code can be seen on my Github page: &nbsp;
<a href="https://github.com/PA4KEV/iOS-Airports" target="_blank" rel="noopener noreferrer">
<img src={`${process.env.PUBLIC_URL}/icons/github.png`} alt="github icon"/>
</a>
</p>
<p>
Source code can be seen on my Github page: &nbsp;
<a href="https://github.com/PA4KEV/iOS-Airports" target="_blank" rel="noopener noreferrer">
<img src={`${process.env.PUBLIC_URL}/icons/github.png`} alt="github icon"/>
</a>
</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-1-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-1-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-1.webp`} />
<img alt="Screenshot of selectable airports" src={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-1.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-1-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-1-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-1.webp`} />
<img alt="Screenshot of selectable airports" src={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-1.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-2-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-2-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-2.webp`} />
<img alt="Screenshot of an air route" src={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-2.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-2-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-2-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-2.webp`} />
<img alt="Screenshot of an air route" src={`${process.env.PUBLIC_URL}/images/projects/ios-airports/screenshot-2.webp`}/>
</picture>
</section>
</div>
</section>
</div>
)
}

View File

@ -4,53 +4,45 @@ import React from 'react';
const KanjiApplication = () => {
return (
<div className='row'>
<div className="sidebar col-3 position-fixed">
<div id="list-example" className="list-group">
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-intro">intro</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-settings">settings</a>
</div>
</div>
<a href='..'>Software</a>
<section id="list-intro" className="content-section">
<h1 className="text-primary">Kanji flashcard Android application</h1>
<h4 className="text-secondary">Personalized Japanese learning</h4>
<p>In my free time I like to learn Japanese. I am married with someone from Japan, so being able talk with her parents in their own language is nice! You also pick up much of the culture through learning the language.</p>
<p>I wanted a personalized way to learn <a href="https://en.wikipedia.org/wiki/Kanji" target="_blank" rel="noopener noreferrer">Kanji</a>. I keep track of the words I want to learn in a small <a href="https://sqlite.org/" target="_blank" rel="noopener noreferrer">SQLite</a> database. If I come across a Japanese word, I can enter it in the database myself, because many language learning applications give you a preset of words, usually of the <a href="https://en.wikipedia.org/wiki/J%C5%8Dy%C5%8D_kanji" target="_blank" rel="noopener noreferrer">joyo Kanji</a>. The database can also be exported and imported to a file from the application.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/logo-w240.webp`} />
<source media="(min-width: 800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/logo.webp`} />
<img alt="MyKanji application logo" src={`${process.env.PUBLIC_URL}/images/projects/mykanji/logo.webp`}/>
</picture>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-intro" className="content-section">
<h1 className="text-primary">Kanji flashcard Android application</h1>
<h4 className="text-secondary">Personalized Japanese learning</h4>
<p>In my free time I like to learn Japanese. I am married with someone from Japan, so being able talk with her parents in their own language is nice! You also pick up much of the culture through learning the language.</p>
<p>I wanted a personalized way to learn <a href="https://en.wikipedia.org/wiki/Kanji" target="_blank" rel="noopener noreferrer">Kanji</a>. I keep track of the words I want to learn in a small <a href="https://sqlite.org/" target="_blank" rel="noopener noreferrer">SQLite</a> database. If I come across a Japanese word, I can enter it in the database myself, because many language learning applications give you a preset of words, usually of the <a href="https://en.wikipedia.org/wiki/J%C5%8Dy%C5%8D_kanji" target="_blank" rel="noopener noreferrer">joyo Kanji</a>. The database can also be exported and imported to a file from the application.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/logo-w240.webp`} />
<source media="(min-width: 800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/logo.webp`} />
<img alt="MyKanji application logo" src={`${process.env.PUBLIC_URL}/images/projects/mykanji/logo.webp`}/>
</picture>
<h4 className="text-secondary">Tools</h4>
<p><a href="https://www.java.com" target="_blank" rel="noopener noreferrer">Java</a> and <a href="https://en.wikipedia.org/wiki/Android_Studio" target="_blank" rel="noopener noreferrer">Android studio</a> were used to create this application.</p>
<h4 className="text-secondary">Tools</h4>
<p><a href="https://www.java.com" target="_blank" rel="noopener noreferrer">Java</a> and <a href="https://en.wikipedia.org/wiki/Android_Studio" target="_blank" rel="noopener noreferrer">Android studio</a> were used to create this application.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-1-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-1-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-1.webp`} />
<img alt="Screenshot of a kanji flashcard" src={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-1.webp`}/>
</picture>
</section>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-1-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-1-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-1.webp`} />
<img alt="Screenshot of a kanji flashcard" src={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-1.webp`}/>
</picture>
</section>
<section id="list-settings" className="content-section">
<h2 className="text-primary">Settings</h2>
<p>By user input, the difficulty of a Kanji is determined. A Kanji that is often guessed wrong will increase in difficulty and can be asked more frequently. Questioning can be done based on time and certain aspects of the Kanji can be shown or hidden. Finally, a dark and light mode offers some more customizability, along with the sizes of the characters.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-2-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-2-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-2.webp`} />
<img alt="Screenshot with application settings" src={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-2.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-3-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-3-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-3.webp`} />
<img alt="Screenshot with database entries" src={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-3.webp`}/>
</picture>
</section>
</div>
<section id="list-settings" className="content-section">
<h2 className="text-primary">Settings</h2>
<p>By user input, the difficulty of a Kanji is determined. A Kanji that is often guessed wrong will increase in difficulty and can be asked more frequently. Questioning can be done based on time and certain aspects of the Kanji can be shown or hidden. Finally, a dark and light mode offers some more customizability, along with the sizes of the characters.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-2-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-2-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-2.webp`} />
<img alt="Screenshot with application settings" src={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-2.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-3-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-3-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-3.webp`} />
<img alt="Screenshot with database entries" src={`${process.env.PUBLIC_URL}/images/projects/mykanji/screenshot-3.webp`}/>
</picture>
</section>
</div>
)
}

View File

@ -4,64 +4,62 @@ import React from 'react';
const MetroidShooter = () => {
return (
<div className='row'>
<a href='..'>Software</a>
<section id="list-intro" className="content-section">
<h1 className="text-primary">Metroid Horizontal Shooter</h1>
<h4 className="text-secondary">Java game</h4>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-intro" className="content-section">
<h1 className="text-primary">Metroid Horizontal Shooter</h1>
<h4 className="text-secondary">Java game</h4>
<p>A simple Java 2D game using Nintendo's <a href="https://en.wikipedia.org/wiki/Metroid" target="_blank" rel="noopener noreferrer">Metroid</a> franchise sprites. This was a school project. This little game I made to practice programming with 2D graphics. It slowly gained more and more features like extra weapons and different levels, because I really enjoyed working on this project.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen1-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen1-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen1-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen1.webp`} />
<img alt="Screenshot" src={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen1.webp`}/>
</picture>
<p>A simple Java 2D game using Nintendo's <a href="https://en.wikipedia.org/wiki/Metroid" target="_blank" rel="noopener noreferrer">Metroid</a> franchise sprites. This was a school project. This little game I made to practice programming with 2D graphics. It slowly gained more and more features like extra weapons and different levels, because I really enjoyed working on this project.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen1-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen1-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen1-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen1.webp`} />
<img alt="Screenshot" src={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen1.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen2-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen2-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen2-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen2.webp`} />
<img alt="Screenshot" src={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen2.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen2-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen2-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen2-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen2.webp`} />
<img alt="Screenshot" src={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen2.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen3-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen3-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen3-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen3.webp`} />
<img alt="Screenshot" src={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen3.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen3-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen3-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen3-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen3.webp`} />
<img alt="Screenshot" src={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen3.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen4-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen4-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen4-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen4.webp`} />
<img alt="Screenshot" src={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen4.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen4-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen4-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen4-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen4.webp`} />
<img alt="Screenshot" src={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen4.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen5-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen5-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen5-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen5.webp`} />
<img alt="Screenshot" src={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen5.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen5-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen5-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen5-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen5.webp`} />
<img alt="Screenshot" src={`${process.env.PUBLIC_URL}/images/projects/metroid/MetroidScreen5.webp`}/>
</picture>
</section>
</div>
</section>
</div>
)
}

View File

@ -4,42 +4,40 @@ import React from 'react';
const RaspberryJukebox = () => {
return (
<div className='row'>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-intro" className="content-section">
<h1 className="text-primary">Raspberry Pi Jukebox</h1>
<h4 className="text-secondary">Streaming internet radio</h4>
<p>Here I used a <a href="https://www.raspberrypi.org/" target="_blank" rel="noopener noreferrer">Raspberry Pi</a> to stream internet radio. <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer">Python</a> and <a href="https://flask.palletsprojects.com/" target="_blank" rel="noopener noreferrer">Flask</a> were used to create a simple website interface that resided on the Raspberry Pi using the Apache web engine. This simple site had buttons to control the LEDs, the station to stream and to adjust the volume.</p>
<p>The LEDs were controlled using an <a href="https://www.arduino.cc/" target="_blank" rel="noopener noreferrer">Arduino</a> and a <a href="https://www.analog.com/media/en/technical-documentation/data-sheets/max7219-max7221.pdf" target="_blank" rel="noopener noreferrer">Maxim MAX7219 IC</a>.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/disassembly-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/disassembly-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/disassembly.webp`} />
<img alt="Jukebox disassembly" src={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/disassembly.webp`}/>
</picture>
<a href='..'>Software</a>
<section id="list-intro" className="content-section">
<h1 className="text-primary">Raspberry Pi Jukebox</h1>
<h4 className="text-secondary">Streaming internet radio</h4>
<p>Here I used a <a href="https://www.raspberrypi.org/" target="_blank" rel="noopener noreferrer">Raspberry Pi</a> to stream internet radio. <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer">Python</a> and <a href="https://flask.palletsprojects.com/" target="_blank" rel="noopener noreferrer">Flask</a> were used to create a simple website interface that resided on the Raspberry Pi using the Apache web engine. This simple site had buttons to control the LEDs, the station to stream and to adjust the volume.</p>
<p>The LEDs were controlled using an <a href="https://www.arduino.cc/" target="_blank" rel="noopener noreferrer">Arduino</a> and a <a href="https://www.analog.com/media/en/technical-documentation/data-sheets/max7219-max7221.pdf" target="_blank" rel="noopener noreferrer">Maxim MAX7219 IC</a>.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/disassembly-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/disassembly-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/disassembly.webp`} />
<img alt="Jukebox disassembly" src={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/disassembly.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/old-interiour-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/old-interiour-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/old-interiour.webp`} />
<img alt="Jukebox old interiour" src={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/old-interiour.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/old-interiour-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/old-interiour-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/old-interiour.webp`} />
<img alt="Jukebox old interiour" src={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/old-interiour.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/led-matrix-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/led-matrix-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/led-matrix.webp`} />
<img alt="L E D Matrix" src={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/led-martix.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/led-matrix-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/led-matrix-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/led-matrix.webp`} />
<img alt="L E D Matrix" src={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/led-martix.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/fully-assembled-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/fully-assembled-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/fully-assembled-w800.webp`} />
<img alt="Fully assembled jukebox with lights" src={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/fully-assembled-w800.webp`}/>
</picture>
</section>
</div>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/fully-assembled-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/fully-assembled-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/fully-assembled-w800.webp`} />
<img alt="Fully assembled jukebox with lights" src={`${process.env.PUBLIC_URL}/images/projects/raspberry-jukebox/fully-assembled-w800.webp`}/>
</picture>
</section>
</div>
)
}

View File

@ -4,48 +4,39 @@ import React from 'react';
const SwivForPi = () => {
return (
<div className='row'>
<div className="sidebar col-3 position-fixed">
<div id="list-example" className="list-group">
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-intro">intro</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-hardware">Hardware</a>
</div>
</div>
<a href='..'>Software</a>
<section id="list-intro" className="content-section">
<h1 className="text-primary">Embedded Game</h1>
<h4 className="text-secondary">Vertical shooter</h4>
<p>A simple vertical space shooter created for the <a href="https://www.raspberrypi.org/" target="_blank" rel="noopener noreferrer">Raspberry Pi</a>. The game is played with regular keyboard and a custom joystick setup. The game was programmed in Python using the <a href="https://www.pygame.org/" target="_blank" rel="noopener noreferrer">PyGame</a> library. This project was mainly to create small game and interface it with a custom hardware setup. The setup uses an analog joystick to control the player's helicopter. An <a href="https://en.wikipedia.org/wiki/Analog-to-digital_converter" target="_blank" rel="noopener noreferrer">ADC (Analog Digital Converter)</a> samples the analog data into digital data so that the Raspberry Pi (version 1, type B) could parse the data.</p>
<img src={`${process.env.PUBLIC_URL}/images/projects/swivforpi/title.webp`} alt="S W I V for Pi title screen"/>
<img src={`${process.env.PUBLIC_URL}/images/projects/swivforpi/screenshot.webp`} alt="S W I V for Pi screenshot"/>
</section>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-intro" className="content-section">
<h1 className="text-primary">Embedded Game</h1>
<h4 className="text-secondary">Vertical shooter</h4>
<p>A simple vertical space shooter created for the <a href="https://www.raspberrypi.org/" target="_blank" rel="noopener noreferrer">Raspberry Pi</a>. The game is played with regular keyboard and a custom joystick setup. The game was programmed in Python using the <a href="https://www.pygame.org/" target="_blank" rel="noopener noreferrer">PyGame</a> library. This project was mainly to create small game and interface it with a custom hardware setup. The setup uses an analog joystick to control the player's helicopter. An <a href="https://en.wikipedia.org/wiki/Analog-to-digital_converter" target="_blank" rel="noopener noreferrer">ADC (Analog Digital Converter)</a> samples the analog data into digital data so that the Raspberry Pi (version 1, type B) could parse the data.</p>
<img src={`${process.env.PUBLIC_URL}/images/projects/swivforpi/title.webp`} alt="S W I V for Pi title screen"/>
<img src={`${process.env.PUBLIC_URL}/images/projects/swivforpi/screenshot.webp`} alt="S W I V for Pi screenshot"/>
</section>
<section id="list-hardware" className="content-section">
<h2 className="text-primary">Hardware</h2>
<p>Simple components were placed onto a breadboard and the joystick's analog resistive data would be converted into digital data. This data would be read by the GPIO pins and used to determine how the helicopter moves over the X- and Y-axis. To help with understanding electronic logic, an oscilloscope was used.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-top-view-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-top-view-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-top-view-w800.webp`} />
<img alt="Breadboard with components top view" src={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-top-view-w800.webp`}/>
</picture>
<section id="list-hardware" className="content-section">
<h2 className="text-primary">Hardware</h2>
<p>Simple components were placed onto a breadboard and the joystick's analog resistive data would be converted into digital data. This data would be read by the GPIO pins and used to determine how the helicopter moves over the X- and Y-axis. To help with understanding electronic logic, an oscilloscope was used.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-top-view-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-top-view-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-top-view-w800.webp`} />
<img alt="Breadboard with components top view" src={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-top-view-w800.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-front-view-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-front-view-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-front-view-w800.webp`} />
<img alt="Breadboard with components front view" src={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-front-view-w800.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/oscilloscope-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/oscilloscope-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/oscilloscope-w800.webp`} />
<img alt="Breadboard with components top view" src={`${process.env.PUBLIC_URL}/images/projects/swivforpi/oscilloscope-w800.webp`}/>
</picture>
</section>
</div>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-front-view-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-front-view-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-front-view-w800.webp`} />
<img alt="Breadboard with components front view" src={`${process.env.PUBLIC_URL}/images/projects/swivforpi/breadboard-front-view-w800.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/oscilloscope-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/oscilloscope-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/swivforpi/oscilloscope-w800.webp`} />
<img alt="Breadboard with components top view" src={`${process.env.PUBLIC_URL}/images/projects/swivforpi/oscilloscope-w800.webp`}/>
</picture>
</section>
</div>
)
}

View File

@ -4,101 +4,91 @@ import React from 'react';
const TeslaMaze = () => {
return (
<div className='row'>
<div className="sidebar col-3 position-fixed">
<div id="list-example" className="list-group">
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-intro">intro</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-gameplay">gameplay</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-woodwork">woodwork</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-lessons-learnt">lessons learnt</a>
</div>
</div>
<a href='..'>Software</a>
<section id="list-intro" className="content-section">
<h1 className="text-primary">TeslaMaze</h1>
<h4 className="text-secondary">Gaming, Woodcraft and Teamwork!</h4>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-intro" className="content-section">
<h1 className="text-primary">TeslaMaze</h1>
<h4 className="text-secondary">Gaming, Woodcraft and Teamwork!</h4>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-logo-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-logo-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-logo.webp`} />
<img alt="TeslaMaze logo" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-logo.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-logo-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-logo-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-logo.webp`} />
<img alt="TeslaMaze logo" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-logo.webp`}/>
</picture>
<p>A team project where the player must align pipes correctly using a Wii remote. The ingame goals would then have effect on a custom built wooden tower. The game was programmed in <a href="https://www.java.com" target="_blank" rel="noopener noreferrer">Java</a>.</p>
<p>This project was made by four people working on both software and hardware. The game uses the <a href="https://en.wikipedia.org/wiki/Wii" target="_blank" rel="noopener noreferrer">Nintendo Wii remote</a> to get input from the player.</p>
</section>
<section id="list-gameplay" className="content-section">
<h2 className="text-primary">Gameplay</h2>
<p>The player must align pipes from the fictional tesla coil to "relay electricity" to a specific point in the game. The game communicates to the <a href="https://www.arduino.cc/" target="_blank" rel="noopener noreferrer">Arduino</a> to power <a href="https://en.wikipedia.org/wiki/Servomotor" target="_blank" rel="noopener noreferrer">servomotors</a> that operate three doors and an elevator.</p>
<p>A team project where the player must align pipes correctly using a Wii remote. The ingame goals would then have effect on a custom built wooden tower. The game was programmed in <a href="https://www.java.com" target="_blank" rel="noopener noreferrer">Java</a>.</p>
<p>This project was made by four people working on both software and hardware. The game uses the <a href="https://en.wikipedia.org/wiki/Wii" target="_blank" rel="noopener noreferrer">Nintendo Wii remote</a> to get input from the player.</p>
</section>
<section id="list-gameplay" className="content-section">
<h2 className="text-primary">Gameplay</h2>
<p>The player must align pipes from the fictional tesla coil to "relay electricity" to a specific point in the game. The game communicates to the <a href="https://www.arduino.cc/" target="_blank" rel="noopener noreferrer">Arduino</a> to power <a href="https://en.wikipedia.org/wiki/Servomotor" target="_blank" rel="noopener noreferrer">servomotors</a> that operate three doors and an elevator.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/gameplay-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/gameplay-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/gameplay-w800.webp`} />
<img alt="TeslaMaze gameplay" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/gameplay-w800.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/gameplay-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/gameplay-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/gameplay-w800.webp`} />
<img alt="TeslaMaze gameplay" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/gameplay-w800.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/screenshot-game-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/screenshot-game-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/screenshot-game.webp`} />
<img alt="TeslaMaze pipe game screenshot" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/screenshot-game.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/screenshot-game-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/screenshot-game-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/screenshot-game.webp`} />
<img alt="TeslaMaze pipe game screenshot" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/screenshot-game.webp`}/>
</picture>
</section>
<section id="list-woodwork" className="content-section">
<h2 className="text-primary">Woodwork</h2>
<p>The tower base is made of wood and has a metal screw elevator. A conductive metal ball has to be elevated up and then roll down three rails. One side of a rail is powered and the other is grounded. The metal ball conducts electricity to blue LED's on the rails when it passes by. Once the ball has reached the bottom of the tower within the time limit, a switch turns on the <a href="https://en.wikipedia.org/wiki/Plasma_globe" target="_blank" rel="noopener noreferrer">plasma globe</a> on the top of the tower and the game is won.</p>
</section>
<section id="list-woodwork" className="content-section">
<h2 className="text-primary">Woodwork</h2>
<p>The tower base is made of wood and has a metal screw elevator. A conductive metal ball has to be elevated up and then roll down three rails. One side of a rail is powered and the other is grounded. The metal ball conducts electricity to blue LED's on the rails when it passes by. Once the ball has reached the bottom of the tower within the time limit, a switch turns on the <a href="https://en.wikipedia.org/wiki/Plasma_globe" target="_blank" rel="noopener noreferrer">plasma globe</a> on the top of the tower and the game is won.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/elevator-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/elevator-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/elevator.webp`} />
<img alt="TeslaMaze screw elevator" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/elevator.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/elevator-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/elevator-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/elevator.webp`} />
<img alt="TeslaMaze screw elevator" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/elevator.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/rails-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/rails-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/rails.webp`} />
<img alt="TeslaMaze rails" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/rails.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/rails-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/rails-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/rails.webp`} />
<img alt="TeslaMaze rails" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/rails.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/tower-base-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/tower-base-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/tower-base.webp`} />
<img alt="TeslaMaze tower base" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/tower-base.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/tower-base-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/tower-base-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/tower-base.webp`} />
<img alt="TeslaMaze tower base" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/tower-base.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/in-progress-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/in-progress-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/in-progress.webp`} />
<img alt="TeslaMaze in progress" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/in-progress.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/in-progress-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/in-progress-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/in-progress.webp`} />
<img alt="TeslaMaze in progress" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/in-progress.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/render-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/render-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/render.webp`} />
<img alt="TeslaMaze 3D render" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/render.webp`}/>
</picture>
</section>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/render-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/render-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/render.webp`} />
<img alt="TeslaMaze 3D render" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/render.webp`}/>
</picture>
</section>
<section id="list-lessons-learnt" className="content-section">
<h2 className="text-primary">Lessons learnt</h2>
<p>This was actually my favourite project to work on! It combined the talent of everyone in our team. We had a very skilled woodworker <i>(who doubled as a good project leader as well)</i> and we all were coding. This project taught me that effective team work with good group synergy, produces great results.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-final-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-final-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-final.webp`} />
<img alt="TeslaMaze final version" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-final.webp`}/>
</picture>
</section>
</div>
<section id="list-lessons-learnt" className="content-section">
<h2 className="text-primary">Lessons learnt</h2>
<p>This was actually my favourite project to work on! It combined the talent of everyone in our team. We had a very skilled woodworker <i>(who doubled as a good project leader as well)</i> and we all were coding. This project taught me that effective team work with good group synergy, produces great results.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-final-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-final-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-final.webp`} />
<img alt="TeslaMaze final version" src={`${process.env.PUBLIC_URL}/images/projects/teslamaze/teslamaze-final.webp`}/>
</picture>
</section>
</div>
)
}

View File

@ -4,57 +4,49 @@ import React from 'react';
const WifiPrototype = () => {
return (
<div className='row'>
<div className="sidebar col-3 position-fixed">
<div id="list-example" className="list-group">
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-wifi">Wi-Fi</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-tech">Technique</a>
</div>
</div>
<a href='..'>Software</a>
<section id="list-wifi" className="content-section">
<h1 className="text-primary">Wi-Fi prototype board</h1>
<h4 className="text-secondary">Embedded internship project</h4>
<p>This project was part of my internship at Dazzletek in Breda. They created intelligent lighting control solutions, but sadly the company no longer exists today. My assignment was to create a prototype that would allow a device to communicate over <a href="https://en.wikipedia.org/wiki/Wi-Fi" target="_blank" rel="noopener noreferrer">Wi-Fi</a>. I worked with <a href="https://en.wikipedia.org/wiki/PIC_microcontrollers" target="_blank" rel="noopener noreferrer">oscilloscopes</a> and electronics to adjust the hardware on the prototype.</p>
<p>I developed a software program using <a href="https://en.wikipedia.org/wiki/Bluegiga" target="_blank" rel="noopener noreferrer">C</a> in the OpenAT framework. At the end of my internship the prototype was realized into a product. The purpose of this assignment was to provide a device which communicates over <a href="https://en.wikipedia.org/wiki/General_Packet_Radio_Service" target="_blank" rel="noopener noreferrer">GPRS</a>, with the ability to communicate that data over Wi-Fi.</p>
<p>Instead of using the Wi-Fi stack, I was encouraged to develop my own data transfer logic over <a href="https://en.wikipedia.org/wiki/Serial_Peripheral_Interface" target="_blank" rel="noopener noreferrer">SPI</a>, which was then read over the oscilloscope.</p>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-wifi" className="content-section">
<h1 className="text-primary">Wi-Fi prototype board</h1>
<h4 className="text-secondary">Embedded internship project</h4>
<p>This project was part of my internship at Dazzletek in Breda. They created intelligent lighting control solutions, but sadly the company no longer exists today. My assignment was to create a prototype that would allow a device to communicate over <a href="https://en.wikipedia.org/wiki/Wi-Fi" target="_blank" rel="noopener noreferrer">Wi-Fi</a>. I worked with <a href="https://en.wikipedia.org/wiki/PIC_microcontrollers" target="_blank" rel="noopener noreferrer">oscilloscopes</a> and electronics to adjust the hardware on the prototype.</p>
<p>I developed a software program using <a href="https://en.wikipedia.org/wiki/Bluegiga" target="_blank" rel="noopener noreferrer">C</a> in the OpenAT framework. At the end of my internship the prototype was realized into a product. The purpose of this assignment was to provide a device which communicates over <a href="https://en.wikipedia.org/wiki/General_Packet_Radio_Service" target="_blank" rel="noopener noreferrer">GPRS</a>, with the ability to communicate that data over Wi-Fi.</p>
<p>Instead of using the Wi-Fi stack, I was encouraged to develop my own data transfer logic over <a href="https://en.wikipedia.org/wiki/Serial_Peripheral_Interface" target="_blank" rel="noopener noreferrer">SPI</a>, which was then read over the oscilloscope.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/antares-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/antares-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/antares.webp`} />
<img alt="Antares main board" src={`${process.env.PUBLIC_URL}/images/projects/dazzletek/antares.webp`}/>
</picture>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/oscilloscope-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/oscilloscope-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/oscilloscope.webp`} />
<img alt="oscilloscope showing S P I protocol" src={`${process.env.PUBLIC_URL}/images/projects/dazzletek/oscilloscope.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/antares-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/antares-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/antares.webp`} />
<img alt="Antares main board" src={`${process.env.PUBLIC_URL}/images/projects/dazzletek/antares.webp`}/>
</picture>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/oscilloscope-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/oscilloscope-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/oscilloscope.webp`} />
<img alt="oscilloscope showing S P I protocol" src={`${process.env.PUBLIC_URL}/images/projects/dazzletek/oscilloscope.webp`}/>
</picture>
</section>
</section>
<section id="list-tech" className="content-section">
<h2 className="text-primary">Technique</h2>
<p>The WF121 by <a href="https://en.wikipedia.org/wiki/Bluegiga" target="_blank" rel="noopener noreferrer">BlueGiga</a>, which used a <a href="https://en.wikipedia.org/wiki/PIC_microcontrollers" target="_blank" rel="noopener noreferrer">PIC32 microcontroller</a>, had to be programmed to accept and transfer data to a specific <a href="https://en.wikipedia.org/wiki/Service_set_(802.11_network)#SSID" target="_blank" rel="noopener noreferrer">SSID</a>. Also the AirPrime SL6087 by <a href="https://www.sierrawireless.com/" target="_blank" rel="noopener noreferrer">Sierra Wireless</a> had to be programmed to relay the data to the Wi-Fi module.</p>
<p>I used <a href="https://www.wireshark.org/" target="_blank" rel="noopener noreferrer">Wireshark</a>, commandline debug and an oscilloscope to monitor the datatranfers. I also built a little <a href="https://en.wikipedia.org/wiki/Registered_jack" target="_blank" rel="noopener noreferrer">RJ45</a> connector that could be plugged on the prototype board so it could be easily programmed. Version control was done in <a href="https://subversion.apache.org/" target="_blank" rel="noopener noreferrer">Subversion</a>.</p>
<section id="list-tech" className="content-section">
<h2 className="text-primary">Technique</h2>
<p>The WF121 by <a href="https://en.wikipedia.org/wiki/Bluegiga" target="_blank" rel="noopener noreferrer">BlueGiga</a>, which used a <a href="https://en.wikipedia.org/wiki/PIC_microcontrollers" target="_blank" rel="noopener noreferrer">PIC32 microcontroller</a>, had to be programmed to accept and transfer data to a specific <a href="https://en.wikipedia.org/wiki/Service_set_(802.11_network)#SSID" target="_blank" rel="noopener noreferrer">SSID</a>. Also the AirPrime SL6087 by <a href="https://www.sierrawireless.com/" target="_blank" rel="noopener noreferrer">Sierra Wireless</a> had to be programmed to relay the data to the Wi-Fi module.</p>
<p>I used <a href="https://www.wireshark.org/" target="_blank" rel="noopener noreferrer">Wireshark</a>, commandline debug and an oscilloscope to monitor the datatranfers. I also built a little <a href="https://en.wikipedia.org/wiki/Registered_jack" target="_blank" rel="noopener noreferrer">RJ45</a> connector that could be plugged on the prototype board so it could be easily programmed. Version control was done in <a href="https://subversion.apache.org/" target="_blank" rel="noopener noreferrer">Subversion</a>.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/wifi-board-prototype-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/wifi-board-prototype-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/wifi-board-prototype.webp`} />
<img alt="Wi-Fi prototype board final product" src={`${process.env.PUBLIC_URL}/images/projects/dazzletek/wifi-board-prototype.webp`}/>
</picture>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/programming-batch-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/programming-batch-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/programming-batch.webp`} />
<img alt="programming a batch" src={`${process.env.PUBLIC_URL}/images/projects/dazzletek/programming-batch.webp`}/>
</picture>
</section>
</div>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/wifi-board-prototype-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/wifi-board-prototype-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/wifi-board-prototype.webp`} />
<img alt="Wi-Fi prototype board final product" src={`${process.env.PUBLIC_URL}/images/projects/dazzletek/wifi-board-prototype.webp`}/>
</picture>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/programming-batch-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/programming-batch-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/dazzletek/programming-batch.webp`} />
<img alt="programming a batch" src={`${process.env.PUBLIC_URL}/images/projects/dazzletek/programming-batch.webp`}/>
</picture>
</section>
</div>
)
}

View File

@ -4,66 +4,58 @@ import React from 'react';
const Windows10Cookbook = () => {
return (
<div className='row'>
<div className="sidebar col-3 position-fixed">
<div id="list-example" className="list-group">
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-intro">Intro</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-mockups">Mockups</a>
</div>
</div>
<a href='..'>Software</a>
<section id="list-intro" className="content-section">
<h1 className="text-primary">Windows 10 Cookbook</h1>
<h4 className="text-secondary">UWP application</h4>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-intro" className="content-section">
<h1 className="text-primary">Windows 10 Cookbook</h1>
<h4 className="text-secondary">UWP application</h4>
<p>This <a href="https://learn.microsoft.com/en-us/windows/uwp/get-started/universal-application-platform-guide" target="_blank" rel="noopener noreferrer">UWP</a> application was built with <a href="https://docs.microsoft.com/en-us/dotnet/csharp/" target="_blank" rel="noopener noreferrer">C#</a> and <a href="https://learn.microsoft.com/en-us/dotnet/desktop/wpf/xaml/?view=netdesktop-6.0" target="_blank" rel="noopener noreferrer">XAML</a>.</p>
<p>This was a school project which retrieved recipies and other data from an API.</p>
<p>Mostly this was to learn quickly how to develop a mobile application on the Windows platform with a responsive design.</p>
<p>This <a href="https://learn.microsoft.com/en-us/windows/uwp/get-started/universal-application-platform-guide" target="_blank" rel="noopener noreferrer">UWP</a> application was built with <a href="https://docs.microsoft.com/en-us/dotnet/csharp/" target="_blank" rel="noopener noreferrer">C#</a> and <a href="https://learn.microsoft.com/en-us/dotnet/desktop/wpf/xaml/?view=netdesktop-6.0" target="_blank" rel="noopener noreferrer">XAML</a>.</p>
<p>This was a school project which retrieved recipies and other data from an API.</p>
<p>Mostly this was to learn quickly how to develop a mobile application on the Windows platform with a responsive design.</p>
<p>
Source code can be seen on my Github page: &nbsp;
<a href="https://github.com/PA4KEV/Win10-Cookbook" target="_blank" rel="noopener noreferrer">
<img src={`${process.env.PUBLIC_URL}/icons/github.png`} alt="github icon"/>
</a>
</p>
<p>
Source code can be seen on my Github page: &nbsp;
<a href="https://github.com/PA4KEV/Win10-Cookbook" target="_blank" rel="noopener noreferrer">
<img src={`${process.env.PUBLIC_URL}/icons/github.png`} alt="github icon"/>
</a>
</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/logo-w240.webp`} />
<source media="(min-width: 800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/logo.webp`} />
<img alt="application logo" src={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/logo.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/logo-w240.webp`} />
<source media="(min-width: 800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/logo.webp`} />
<img alt="application logo" src={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/logo.webp`}/>
</picture>
<p></p>
<p></p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/user-interface-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/user-interface-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/user-interface-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/user-interface.webp`} />
<img alt="user interface" src={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/user-interface.webp`}/>
</picture>
</section>
<section id="list-mockups" className="content-section">
<h2 className="text-primary">Mockups on laptop and mobile</h2>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/user-interface-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/user-interface-w480.webp`} />
<source media="(min-width: 1200px) and (max-width: 1799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/user-interface-w800.webp`} />
<source media="(min-width: 1800px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/user-interface.webp`} />
<img alt="user interface" src={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/user-interface.webp`}/>
</picture>
</section>
<section id="list-mockups" className="content-section">
<h2 className="text-primary">Mockups on laptop and mobile</h2>
<p>These are mockups on other devices, using screenshots of the application.</p>
<p>These are mockups on other devices, using screenshots of the application.</p>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/laptop-mockup-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/laptop-mockup-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/laptop-mockup.webp`} />
<img alt="laptop mockup" src={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/laptop-mockup.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/laptop-mockup-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/laptop-mockup-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/laptop-mockup.webp`} />
<img alt="laptop mockup" src={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/laptop-mockup.webp`}/>
</picture>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/mobile-mockup-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/mobile-mockup-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/mobile-mockup.webp`} />
<img alt="laptop mockup" src={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/mobile-mockup.webp`}/>
</picture>
</section>
</div>
<picture>
<source media="(max-width: 799px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/mobile-mockup-w240.webp`} />
<source media="(min-width: 800px) and (max-width: 1199px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/mobile-mockup-w480.webp`} />
<source media="(min-width: 1200px)" srcset={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/mobile-mockup.webp`} />
<img alt="laptop mockup" src={`${process.env.PUBLIC_URL}/images/projects/windows10cookbook/mobile-mockup.webp`}/>
</picture>
</section>
</div>
)
}

View File

@ -21,6 +21,28 @@ const SoftwareMain = () => {
</ul>
<hr />
<h2>{getString('software_projects')}</h2>
<div style={{display: "inline-block"}}>
<ul>
<li><a href="./project/kanji-application">{getString('kanji_application')}</a></li>
<li><a href="./project/dxp-development">{getString('dxp_development')}</a></li>
<li><a href="./project/wifi-prototype">{getString('wifi_prototype')}</a></li>
<li><a href="./project/embedded-game">{getString('embedded_game')}</a></li>
<li><a href="./project/raspberry-pi-jukebox">{getString('raspberry_pi_jukebox')}</a></li>
<li><a href="./project/teslamaze">{getString('teslamaze')}</a></li>
</ul>
</div>
<div style={{display: "inline-block"}}>
<ul>
<li><a href="./project/embedded-internet-radio">{getString('embedded_internet_radio')}</a></li>
<li><a href="./project/windows10-cookbook">{getString('windows10_cookbook')}</a></li>
<li><a href="./project/ios-airports">{getString('ios_airports')}</a></li>
<li><a href="./project/festival-simulator">{getString('festival_simulator')}</a></li>
<li><a href="./project/boebot">{getString('boebot')}</a></li>
<li><a href="./project/attachment-module">{getString('attachment_module')}</a></li>
</ul>
</div>
<hr />
<h2>{getString('education')}</h2>
{educationData.education.map((edu, index) => (
<div key={edu.name + index}>

View File

@ -6,7 +6,6 @@ import BlogPage from './Pages/Plamo/BlogPage';
import CSharpPage from './Pages/Software/csharp/CSharpPage';
import ElmPage from './Pages/Software/elm/ElmPage';
// Japan
export const japaneseRoutes = languages.map(lang => {
const pages = ['but', 'cheat-sheet', 'contrast-particle', 'dake-vs-shika', 'expressions', 'if-when', 'japanese-scale-modelling-tools', 'mae-ni-ato-de', 'particles', 'rashii-kamoshirenai-darou', 'tameni-youni-noni', 'te-form', 'te-oku', 'toka-tari-shi', 'verbs'];
@ -26,6 +25,14 @@ export const plamoBlogRoutes = languages.map(lang => {
return <Route key={`${lang}-${page}`} exact path={path} element={<BlogPage mdPath={mdPath} />} />;
});
}).flat();
export const plamoEquipmentRoutes = languages.map(lang => {
const pages = ['airbrush-cabine'];
return pages.map(page => {
const path = `/${lang}/plamo/equipment/${page}`;
const mdPath = `Plamo/equipment/${lang}/${page}.md`;
return <Route key={`${lang}-${page}`} exact path={path} element={<BlogPage mdPath={mdPath} />} />;
});
}).flat();
// Software
export const programmingLanguageRoutes = languages.map(lang => {

View File

@ -37,7 +37,8 @@ const Navigation = () => {
<li><Link reloadDocument to={currentLanguage + '/japan/'} className="dropdown-item">{getString('japan')}</Link></li>
<li><hr className="dropdown-divider" /></li>
<li><Link reloadDocument to={currentLanguage + '/radio/'} className="dropdown-item">{getString('radio_amateur')}</Link></li>
<li className="hidden"><Link reloadDocument to={currentLanguage + '/scalemodel/'} className="dropdown-item">{getString('scalemodel')}</Link></li>
<li><hr className="dropdown-divider" /></li>
<li><Link reloadDocument to={currentLanguage + '/plamo/'} className="dropdown-item">{getString('plamo')}</Link></li>
<li><hr className="dropdown-divider" /></li>
<li><Link reloadDocument to={currentLanguage + '/software/'} className="dropdown-item">{getString('software')}</Link></li>
</ul>