diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 85d8eff..e8fde1d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,4 +2,7 @@ * @leigh-hackspace/infra # Website content is managed by the Web Editors team -content/* @leigh-hackspace/web-editors \ No newline at end of file +/content/ @leigh-hackspace/web-editors + +# Membership data is managed by the directors +/data/memberships.yaml @leigh-hackspace/directors diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..dd84ea7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..bbcbbe7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/deploy-production.yml b/.github/workflows/deploy-production.yml index 058d32d..61277b2 100644 --- a/.github/workflows/deploy-production.yml +++ b/.github/workflows/deploy-production.yml @@ -31,7 +31,7 @@ jobs: build: runs-on: ubuntu-latest env: - HUGO_VERSION: 0.122.0 + HUGO_VERSION: 0.124.1 steps: - name: Install Hugo CLI run: | @@ -46,7 +46,7 @@ jobs: fetch-depth: 0 - name: Setup Pages id: pages - uses: actions/configure-pages@v4 + uses: actions/configure-pages@v5 - name: Install Node.js dependencies run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true" - name: Build with Hugo diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 88548fc..0aa5944 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,5 +1,5 @@ # Run tests on the website build -name: Test +name: Test - Run a test build on: push: @@ -17,7 +17,7 @@ jobs: build: runs-on: ubuntu-latest env: - HUGO_VERSION: 0.122.0 + HUGO_VERSION: 0.124.1 steps: - name: Install Hugo CLI run: | diff --git a/.gitignore b/.gitignore index c8ff03a..c691a56 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ public resources .hugo_build.lock +.DS_Store diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 78ae450..651d69a 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,11 +2,12 @@ "version": "2.0.0", "tasks": [ { - "type": "hugo", - "task": "server draft", - "group": "build", - "problemMatcher": [], - "label": "hugo: Serve draft site" + "label": "Test Site Locally", + "command": "make", + "args": [ + "serve" + ], + "problemMatcher": [] } ] } \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..68461ad --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Leigh Hackspace + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 2713df6..7ba6ba1 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,23 @@ # Leigh Hackspace Website - Hugo Edition -Hugo version: 0.122 +Hugo version: 0.124.1 -## Dev Mode +## Contributing -To run the site locally you can do the following: +Looking for something to contribute to the website? Check out the ["Good First Issues"](https://github.com/leigh-hackspace/website-hugo/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) tag in the Issues section for tasks that are simple, but need doing. + +All changes to the website must be done on a branch and pushed through the GitHub pull requests workflow. If you have any questions about this process then contact the [Tech Infrastructure](https://wiki.leighhack.org/membership/useful_contacts/#tech-infrastructure) people. + +### Build the site locally + +To build the site locally you can do the following: * Download [Hugo extended edition](https://github.com/gohugoio/hugo/releases/) (named hugo_extended). -* Check out repo +* Check out repo (`git clone https://github.com/leigh-hackspace/website-hugo`) * Run `hugo serve -D --gc -w -F` (add -F to show content with future dates) or `make serve` (if you have `make` installed) * Go to `http://localhost:1313/` to view the local instance. -The site will be updated in real time with any changes made to the site. - -## Making Changes - -All changes to the website must be done on a branch and pushed through the GitHub pull requests workflow. If you have any questions about this process then contact the [Tech Infrastructure](https://wiki.leighhack.org/membership/useful_contacts/#tech-infrastructure) people. +The site will be updated in real-time with any changes made to the site files. ## Deployment @@ -23,18 +25,62 @@ Branches are automatically deployed to [https://web-test.leighhack.org](https:// ## Common Tasks -### New Blog Post +### How do I add images to posts / What custom shortcodes are available? -* Download and install Hugo -* Run `hugo new blog//name-of-post/index.md`, and a new file will be created in the right folder. +We have a few shortcodes that you can use: + +#### `image` + +`image` adds a image and manages the sizing and formatting. + +``` +{{< image src="netatalk.png" width="400x" class="is-pulled-right" title="The Netatalk logo.">}} +``` + +* `src` - The name of the image file, this can be a PNG, JPEG, or WEBP, the path is relevant to the file you're adding it into. +* `class` - Is a CSS class that'll be applied to the `figure` created to show this image, common ones are `is-pulled-left` and `is-pulled-right`, more can be found in the [Bulma helpers](https://bulma.io/documentation/helpers). +* `title` - This is the title and alt text used for the image. +* `width` - The maximum dimensions of the image, this can be used in a few ways, either defining just the width (`400`), defining scaling to a width `400x`, or a specific width and height (`400x600`). Ideally try to use `400x` to keep image scaling working as expected. + +#### `gallery` + +`gallery` surrounds a group of image tags and makes a rotating gallery of the images: + +``` +{{< gallery >}} +{{< image src="network-browser.jpg" title="Mac OS 9.2.2 'Network Browser' showing the 'nas-afp' service available via AFP over AppleTalk.">}} +{{< image src="osx-finder.png" title="Mac OS X 10.4 Finder showing the 'nas-afp' service available via AFP over TCP/IP.">}} +{{< image src="sonoma-finder.png" title="macOS Sonoma Finder showing the 'nas-afp' service available via AFP over TCP/IP.">}} +{{< /gallery >}} +``` + +#### `rawhtml` + +`rawhtml` can be used to inject HTML from your Markdown post into the finished page. **It is really not advised to do this, the retro theme will ignore any HTML in these tags**. + +For example, this is used on the map page to inject the `div` required to render to OpenLayers map: + +``` +{{< rawhtml >}} +
+{{}} +``` + +### How to create a new blog post + +* Download and install [Hugo](https://github.com/gohugoio/hugo/releases/) (the extended edition) +* Run `hugo new blog//name-of-post`, and a new folder will be created in the year folder with a `index.md` with the post. * Update the `author` and `author_email` values * Add a `subtitle` +* If you've posted the blog elsewhere, add the `original_url` value to link to your original post URL. +* Place any images in the folder that was created for your post. +* Set `listing_image` to the image you'll want on the blog listing page ([https://www.leighhack.org/blog/](https://www.leighhack.org/blog/)) * Run Dev Mode (above), or `make serve` and view your post. -### Updating Membership Plans +### How to update the membership plans The membership plan data is held in a YAML file, this is used by the Hackspace API and other tools as well. -* Edit [data/memberships.yaml](data/memberships.yaml), follow the format of existing entries. +* Edit [data/memberships.yaml](data/memberships.yaml), following the format of existing entries. * Links are standard URIs and can support any of the normal formats (mailto:, etc). - \ No newline at end of file + diff --git a/assets/js/calendar.js b/assets/js/calendar.js index 4a39add..edf6e8c 100644 --- a/assets/js/calendar.js +++ b/assets/js/calendar.js @@ -1,6 +1,7 @@ var events = []; $(document).ready(function () { + $('div#calendar p#nojs').hide(); // Hide the NoJS message $.getJSON('https://api.leighhack.org/events', function (data) { data.forEach(function (event) { events.push({ diff --git a/assets/js/site.js b/assets/js/site.js index 6ecd3e7..1069294 100644 --- a/assets/js/site.js +++ b/assets/js/site.js @@ -19,6 +19,7 @@ $(document).ready(function () { } else { $('span#hackspace-status').html('Closed'); } + $('div#hackspace-open').fadeIn('slow'); } // 'printers' shortcode diff --git a/config.toml b/config.toml index 372f87c..ea1df41 100644 --- a/config.toml +++ b/config.toml @@ -69,6 +69,12 @@ name = "Events" pageRef = "events" weight = 6 +[[menu.main]] +name = "Donate" +pageRef = "Donate" +URL = "https://www.paypal.com/donate/?hosted_button_id=G9AJ2HR3SDQ3J" +weight = 7 + [[menu.policies]] name = "Code of Conduct" pageRef = "policies/code_of_conduct" diff --git a/content/_index.md b/content/_index.md index a4ae90d..6bca658 100644 --- a/content/_index.md +++ b/content/_index.md @@ -2,19 +2,21 @@ title: Welcome! subtitle: Leigh Hackspace is a social enterprise created for the benefit of our members and the wider Leigh community. layout: home -hero_image: rose_logo.svg +hero_image: long_logo_solo_whitebg.svg --- +{{< eventbrite >}} + {{< openstatus >}} | Day | Opening Times | | --------- | ------------- | -| Monday | Closed | -| Tuesday | 14:00 - 20:00 | -| Wednesday | 14:00 - 20:00 | +| Monday | 18:30 - 21:00 | +| Tuesday | 14:00 - 21:00 | +| Wednesday | 14:00 - 21:00 | | Thursday | Closed | | Friday | Closed | | Saturday | 12:00 - 17:00 | | Sunday | Closed | -We currently operate reduced opening hours due to member availability. The hackspace can be open outside of these hours and a banner above will appear when it is open, otherwise please check on [Slack](https://join.slack.com/t/leighhack/shared_invite/enQtNDYzMjEyMDMxNDExLTE1MWY5N2IwMzdhMzQ0ZWFiNDkyNzJmMGM1ZmFkODcwMGM5ODFmYmI4MjhmM2JiMWEyY2E3NTRjMTQzMzljZWU). \ No newline at end of file +We currently operate reduced opening hours due to member availability. The hackspace can be open outside of these hours and a banner above will appear when it is open, otherwise please check on [Slack](https://join.slack.com/t/leighhack/shared_invite/enQtNDYzMjEyMDMxNDExLTE1MWY5N2IwMzdhMzQ0ZWFiNDkyNzJmMGM1ZmFkODcwMGM5ODFmYmI4MjhmM2JiMWEyY2E3NTRjMTQzMzljZWU). diff --git a/content/blog/2023/old-webcam-on-modern-linux/index.md b/content/blog/2023/old-webcam-on-modern-linux/index.md index 115ddcf..a60b324 100644 --- a/content/blog/2023/old-webcam-on-modern-linux/index.md +++ b/content/blog/2023/old-webcam-on-modern-linux/index.md @@ -11,6 +11,7 @@ tags: author: Andrew Williams author_email: andy@tensixtyone.com listing_image: camera.png +original_url: https://nikdoof.com/posts/2023/old-webcam-on-modern-linux/ --- {{< image src="camera.png" width="400x" class="is-pulled-right" title="The Trust WB-1200P, a webcam from the early days of USB devices.">}} diff --git a/content/blog/2023/powerbook-g4-disk-replacement/index.md b/content/blog/2023/powerbook-g4-disk-replacement/index.md index ae09f1f..52fb9a6 100644 --- a/content/blog/2023/powerbook-g4-disk-replacement/index.md +++ b/content/blog/2023/powerbook-g4-disk-replacement/index.md @@ -11,6 +11,7 @@ draft: false author: Andrew Williams author_email: andy@tensixtyone.com listing_image: open.jpg +original_url: https://nikdoof.com/posts/2023/powerbook-g4-disk-replacement/ --- In October 2003, I made my first leap into using an Apple device. For quite some time I'd been trying to find a reasonable and portable machine for daily use, and I had slowly gotten frustrated with the current offerings by Dell, HP, and other major laptop manufacturers. In the hunt for something new, I picked a Powerbook G4 12". This machine was my daily workhorse for several years and at the end of its life, it was stuffed into a draw and forgotten about. Sometime around 2014 when I was purchasing a new Macbook Pro I decided to grab my old laptop out of storage and get it booted to hopefully pull a few files from the system. I had lost the power adapter and (obviously) the battery had given up. I purchased a new power adapter on eBay and ended up throwing everything back in the drawer to sort out another day. diff --git a/content/blog/2024/arcade_cabinet/images/cabinets_lined_up.jpg b/content/blog/2024/arcade_cabinet/images/cabinets_lined_up.jpg new file mode 100644 index 0000000..0d56943 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/cabinets_lined_up.jpg differ diff --git a/content/blog/2024/arcade_cabinet/images/cabinets_played.jpg b/content/blog/2024/arcade_cabinet/images/cabinets_played.jpg new file mode 100644 index 0000000..58feeed Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/cabinets_played.jpg differ diff --git a/content/blog/2024/arcade_cabinet/images/case_production_line.jpg b/content/blog/2024/arcade_cabinet/images/case_production_line.jpg new file mode 100644 index 0000000..7f53cb6 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/case_production_line.jpg differ diff --git a/content/blog/2024/arcade_cabinet/images/cutting_cases.jpg b/content/blog/2024/arcade_cabinet/images/cutting_cases.jpg new file mode 100644 index 0000000..31eee42 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/cutting_cases.jpg differ diff --git a/content/blog/2024/arcade_cabinet/images/drilling_holes.jpg b/content/blog/2024/arcade_cabinet/images/drilling_holes.jpg new file mode 100644 index 0000000..32dc7a3 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/drilling_holes.jpg differ diff --git a/content/blog/2024/arcade_cabinet/images/final_cabinet_console.jpg b/content/blog/2024/arcade_cabinet/images/final_cabinet_console.jpg new file mode 100644 index 0000000..87237d8 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/final_cabinet_console.jpg differ diff --git a/content/blog/2024/arcade_cabinet/images/final_cabinet_full.jpg b/content/blog/2024/arcade_cabinet/images/final_cabinet_full.jpg new file mode 100644 index 0000000..e8091d4 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/final_cabinet_full.jpg differ diff --git a/content/blog/2024/arcade_cabinet/images/fusion_design_1.jpg b/content/blog/2024/arcade_cabinet/images/fusion_design_1.jpg new file mode 100644 index 0000000..9e62fb8 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/fusion_design_1.jpg differ diff --git a/content/blog/2024/arcade_cabinet/images/fusion_design_2.jpg b/content/blog/2024/arcade_cabinet/images/fusion_design_2.jpg new file mode 100644 index 0000000..42273d1 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/fusion_design_2.jpg differ diff --git a/content/blog/2024/arcade_cabinet/images/loading_cabinets.jpg b/content/blog/2024/arcade_cabinet/images/loading_cabinets.jpg new file mode 100644 index 0000000..0831e37 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/loading_cabinets.jpg differ diff --git a/content/blog/2024/arcade_cabinet/images/note-01.png b/content/blog/2024/arcade_cabinet/images/note-01.png new file mode 100644 index 0000000..6341dc3 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/note-01.png differ diff --git a/content/blog/2024/arcade_cabinet/images/note-02.png b/content/blog/2024/arcade_cabinet/images/note-02.png new file mode 100644 index 0000000..1443be6 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/note-02.png differ diff --git a/content/blog/2024/arcade_cabinet/images/note-03.png b/content/blog/2024/arcade_cabinet/images/note-03.png new file mode 100644 index 0000000..99cb893 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/note-03.png differ diff --git a/content/blog/2024/arcade_cabinet/images/note-04.png b/content/blog/2024/arcade_cabinet/images/note-04.png new file mode 100644 index 0000000..89478eb Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/note-04.png differ diff --git a/content/blog/2024/arcade_cabinet/images/primed_cases.jpg b/content/blog/2024/arcade_cabinet/images/primed_cases.jpg new file mode 100644 index 0000000..9a69410 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/primed_cases.jpg differ diff --git a/content/blog/2024/arcade_cabinet/images/prototype_case.jpg b/content/blog/2024/arcade_cabinet/images/prototype_case.jpg new file mode 100644 index 0000000..dd71f68 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/prototype_case.jpg differ diff --git a/content/blog/2024/arcade_cabinet/images/wiring_loom.jpg b/content/blog/2024/arcade_cabinet/images/wiring_loom.jpg new file mode 100644 index 0000000..8927e05 Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/wiring_loom.jpg differ diff --git a/content/blog/2024/arcade_cabinet/images/wiring_up_case.jpg b/content/blog/2024/arcade_cabinet/images/wiring_up_case.jpg new file mode 100644 index 0000000..ba3bd0a Binary files /dev/null and b/content/blog/2024/arcade_cabinet/images/wiring_up_case.jpg differ diff --git a/content/blog/2024/arcade_cabinet/index.md b/content/blog/2024/arcade_cabinet/index.md new file mode 100644 index 0000000..817eb8a --- /dev/null +++ b/content/blog/2024/arcade_cabinet/index.md @@ -0,0 +1,147 @@ +--- +title: "Can You Make It Bigger? - A Journey In Building Arcade Cabinets" +subtitle: "" +date: 2024-06-23T07:40:38Z +tags: + - CNC + - Electronics + - Raspberry Pi +draft: false +author: Kian Ryan +author_email: kian@orangetentacle.co.uk +listing_image: images/final_cabinet_full.jpg +--- + +__This one started out as an idea.__ + +Dan Hardiker from [Devoxx UK](https://www.devoxx.co.uk/) contacted me with an idea: + +> _"We want to make a bunch of games with our sponsors, and play them on a bunch of small arcade cabinets. But we also want to +> take the cabinets to a some other events."_ + +I like small, well defined projects, and this one fitted the bill. We can do this. + +_Small, well defined projects._ + + +Okay. So first thoughts immediately went to the [Picade](https://shop.pimoroni.com/products/picade). The Picade is a small arcade cabinet +from [Pimoroni](https://shop.pimoroni.com/). It's great, I have one. +It lives upstairs in my second bedroom, and when I need a bit of quiet time, I use it to play Frogger. I'm a Frogger demon. + +But while it's quite small, it's not easy to store. It's arcade cabinet shaped, and doesn't pack or stack well. + +What if we could build an arcade laptop? Something that could be folded down between events and stored away easily? + +{{< clearfix >}} + +{{}} +{{}} +{{}} + +{{< clearfix >}} + +When I start a project, I sketch, rather than go straight to CAD. I like to have ideas on paper, or more recently, +on digital paper, before I start opening up a CAD program. It won't be perfect, but I'll have some idea of the shape +of the thing before I start working through something I plan on making. CAD software can occassionally be unforgiving, +and it likes to have a plan of what you want to build. You can vary that plan - but having at least part of that plan up +front helps. + +We start with a "Picade in a case". 10" screen, Raspberry Pi 4, and an arcade console with a removable stick to allow the case +to be closed. Technically it works, and I take it to the team. It fills the portable part, but doesn't look "Arcade-y" enough. +Fair. Can we make it look more like an arcade cabinet. + +{{< clearfix >}} + +{{}} +{{}} + +{{< clearfix >}} + +This conversation goes forwards and backwards for a few iterations where we play with bartop designs, etc until we hit +what they _really_ want. + +> "You want full size arcade cabinets, don't you?" + +So how do we deliver full size arcade cabinets, that are still ultimately, _portable_ and _storable_. + +The answer is you do it in parts. The idea of "all the bits in the case" still works, somewhere for all the electronics to live. Monitor, +Raspberry Pi and controls. Then we build a separate cabinet for the case to slot in to. Because our CNC bed is 80cm square, +the cabinet is split in 2, giving a total height of 1.6m. Added benefit - if you want a bartop cabinet for some events, you just use +the top half. The cabinet slots together like flat pack furniture, using slots and furniture bolts for assembly. At the +end of the event, remove the bolts, flatten the case and store between events. + + +Once we were happy with the general idea, we designed the prototype in Fusion 360, and cut the prototype on our Shapeoko XXL. +The electronics case is cut from 9mm MDF and the cabinet from 18mm MDF. The console and display frame are cut from 5mm acrylic. +Assembly of the electronics case is done with glue, with the console and surround mounted using M3 bolts and self tapping inserts. + +{{< clearfix >}} + +{{}} +{{}} +{{}} + +{{< clearfix >}} + +[An archive of the Fusion 360 project is available on Github.](https://github.com/leigh-hackspace/arcade-cabinet) + +To kit the electronics, we used an off the shelf monitor - a Cooler Master GA241, a Raspberry Pi 4 +running RetroArch, an Sanwa JLF arcade stick modified with a Link EX Groove Quick Release and 10 buttons. The GA241 monitor is powered +by 12V, which allows us to nicely split a single 12V/4A power supply for monitor and Pi (using a buck converter). + +> Note on suppliers: We used Arcade World UK for a large amount of this build, but they appear to have disappeared. Since +> the original build, we've been using [Arcade Express](https://www.arcadexpress.com), a Spanish Company. Import charges +> may apply when using them. + +{{< clearfix >}} + +{{}} +{{}} + +{{< clearfix >}} + + +The Devoxx UK games were built using [PyGame](https://www.pygame.org/) - [Dan Hardiker](https://twitter.com/dhardiker) came down the weekend before the +event and spent time getting the games working on the machines. There's nothing like a deadline. Running right up +against it, we painted the cabinets black and drove them down for setup at the Business Design Centre in London. + +{{< clearfix >}} + +{{}} +{{}} +{{}} + +{{< clearfix >}} + + +They were received well, and performed great for the duration of the event. Dan and the crew then did exactly what the +cabinets were designed to do - they removed the electronic cases, removed the bolts, dropped the cabinets flat and packed +them for the next event. + +{{< clearfix >}} + +{{}} +{{}} + +{{< clearfix >}} + +But we're not quite done. The event had gone well, but our prototype was still looking ... well, like a prototype. And +a Hackspace without an Arcade Cabinet isn't really a Hackspace. So we recut the side panels to the same profile as the Devoxx cabinets, +gave ours a lick of paint, and using a Player-X board, some more components and a trackball, added some extra rizz for two player action and more game modes. + +{{< clearfix >}} + +{{}} +{{}} + +{{< clearfix >}} + +It's already been to [Elecromagnetic Field](https://www.emfcamp.org/), where it was used to run [Pico-8](https://www.lexaloffle.com/pico-8.php) games from [Johan Peitz](https://johanpeitz.itch.io/) in the Family Tent, and it'll be making an appearance at the +[International Discworld Convention](https://dwcon.org/) in August, playing the original Discworld point and click games using [ScummVM](https://www.scummvm.org/). + +If you drop by the [Hackspace](/index.md), you're more than welcome to play on it. + +Leigh Hackspace is open to commissions, and we're also keen on teaching people the skills to make for themselves. + +Our [Summer of Making]({{< ref "/blog/2024/summer-of-making/index.md" >}}), has a range of skills that can help get you started, or if +you have a project in mind, please [come and talk to us](mailto:directors@leighhack.org). \ No newline at end of file diff --git a/content/blog/2024/creating-an-appletalk-nas/index.md b/content/blog/2024/creating-an-appletalk-nas/index.md index feeca9b..e52a300 100644 --- a/content/blog/2024/creating-an-appletalk-nas/index.md +++ b/content/blog/2024/creating-an-appletalk-nas/index.md @@ -10,6 +10,7 @@ draft: false author: Andrew Williams author_email: andy@tensixtyone.com listing_image: network-browser.jpg +original_url: https://nikdoof.com/posts/2024/creating-an-appletalk-nas/ --- {{< image src="netatalk.png" width="400x" class="is-pulled-right" title="The Netatalk logo.">}} diff --git a/content/blog/2024/hackbots-part-2/.DS_Store b/content/blog/2024/hackbots-part-2/.DS_Store new file mode 100644 index 0000000..f1d9011 Binary files /dev/null and b/content/blog/2024/hackbots-part-2/.DS_Store differ diff --git a/content/blog/2024/hackbots-part-2/images/codepen_screenshot.png b/content/blog/2024/hackbots-part-2/images/codepen_screenshot.png new file mode 100644 index 0000000..c4e41a9 Binary files /dev/null and b/content/blog/2024/hackbots-part-2/images/codepen_screenshot.png differ diff --git a/content/blog/2024/hackbots-part-2/images/export_as_css.png b/content/blog/2024/hackbots-part-2/images/export_as_css.png new file mode 100644 index 0000000..7805027 Binary files /dev/null and b/content/blog/2024/hackbots-part-2/images/export_as_css.png differ diff --git a/content/blog/2024/hackbots-part-2/images/hackbot.jpg b/content/blog/2024/hackbots-part-2/images/hackbot.jpg new file mode 100644 index 0000000..4098aeb Binary files /dev/null and b/content/blog/2024/hackbots-part-2/images/hackbot.jpg differ diff --git a/content/blog/2024/hackbots-part-2/images/paletton1.png b/content/blog/2024/hackbots-part-2/images/paletton1.png new file mode 100644 index 0000000..47893a3 Binary files /dev/null and b/content/blog/2024/hackbots-part-2/images/paletton1.png differ diff --git a/content/blog/2024/hackbots-part-2/index.md b/content/blog/2024/hackbots-part-2/index.md new file mode 100644 index 0000000..b244a8d --- /dev/null +++ b/content/blog/2024/hackbots-part-2/index.md @@ -0,0 +1,188 @@ +--- +title: "The Hackbots Project II" +subtitle: "Making Simple Robots That Anyone Can Build (Pt. 2)" +date: 2024-03-18T07:40:38Z +tags: + - Rasberry Pi Pico + - Robots + - Electronics +draft: false +author: Paul Williams +author_email: phyushin@gmail.com +listing_image: images/hackbot.jpg +--- + +## Continuing the Bot Building Process +So, we'll continue from where we left on last a little while ago with our bot building blog [posts][1]. +We'd got to the MK IV if memory serves... Next on the list of things to do is to make our bot interface page nice and pretty. + +## Enter, CSS +Because we're using a very simple webserver on the [Raspbery Pi Pico W][2] and because the code handily returned from our `generateHTML()` function is effectively the page that's served by the websever; we know this is a good place to add a little customisation for our robot - make our page a little _prettier_. + +## CodePen +When prototyping, it's always much more satisfying to see the changes happen quickly, as opposed to editing our `generateHTML()` function, uploading to the bot, connecting to our bot, visiting the url... it's a lot of steps - so, to make this a bit easier we're going to use a nice tool called [CodePen][3], our first step is to rip out the HTML from the `generateHTML()` function and paste it into the HTML window, like so: +{{< image src="images/codepen_screenshot.png" title="HTML & CSS editor windows above, results below">}} +The result of the code is shown underneath the HTML and CSS editor windows, We've made a couple of modifications from our original `generateHTML()` function to make it easier to work with CSS: + +```python +html = f""" + + + """ +return html +``` + +The above code is snipped to keep things simple, but what it does is use python's [_string format_][5] functionality to add the variable `style` with the the style we read into the variable from the `style.css` file (more on that a little later). + +We've also moved `generateHTML()` into its own file (`html.py`) and used parameters to drop in from the main program; we import the function into `main.py` by adding the following code to the top of our `main.py`: + +```python +from html import generateHTML +``` + +This allows us to call `generateHTML()` like we did previously, it's just tidied away in its own file now... We've also added the following code to the beginning of the function - which will allow us to use an _exteral_ style sheet (see I told you more on that later): +```python +style = "" +with open("./style.css","r") as f: + style = f.read() +``` +Now, once we're done with making the code look _pretty_ in CodePen we can just drop the code from the _CSS_ window into the `style.css` file and it will make the controller page all nice and pretty too! Great Stuff! + +## Paletton +A good place to grab some colours that go well together is [Paletton][3], For the purposes of this guide however we're only going to pick a primary colour but don't let that stop you from adding a little extra _flare_, pick a colour you like the look of like so: +{{< image src="images/paletton1.png" title="Paletton Colour Picker">}} + +Then, once you're happy with your colourcscheme - go to the export and select _as CSS_: +{{< image src="images/export_as_css.png" title="Export - listing colours that go well together">}} +Don't worry if the export doesn't work, as all the relevant colour information (Hex values) can be grabbed right off this page too! +You should end up with something like this in your `style.css` file: +```css +:root{ + --color-primary-0 : #679933 ; + --color-primary-1 : #C0E699 ; + --color-primary-2 : #90BF60 ; + --color-primary-3 : #437313 ; + --color-primary-4 : #274D00 ; + --color-white : #ffffff ; + --color-black : #000000 ; +} +button { + width:175px; + height:100px; + background-color: var(--color-primary-0); + color: var(--color-white); + font-size:25pt +} +``` +Where the `:root` _selector_ contains the variable namnes used for the colours - you don't have to do it exactly like this but it's done here for clarity. + +## The generateHTML() function +Once you're finished, you should end up with something like this in your `generateHTML()` function: + +```python +def generateHTML(): + style = "" + + with open("./style.css","r") as f: + style = f.read() + + html = f""" + + + Hackspace Bot + + + +
+
+ + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ """ + # this bit is for debugging we can remove in finished branch + html = html + f""" +
+ + + + + + + + + + + +
SSIDPASSWORDIP
{ssid}{password}{ap.ifconfig()}
+
+ + + + """ + return html +``` + +_Note: we already have the external stylesheet file `stlye.css` generated_ which the code opens and reads the contents into the `style` variable, this, in turn is replaced using python's _format string_ functionality we talked about earlier. We write the code in this way as it allows us to easily change the _style_ of our buttons simply by replacing the colours in the `style.css` + +## Finally, secrets.py +The `secrets.py` file is where we, well... store our secrets - sounds pretty obvious right? +The benefit of doing it this way is that we only need to make changes to the one file and they'll be reflected everywhere, which is a common theme in programming sometimes referred to as the [DRY Principle][6]. + +Our `secrets.py` should look something like this: + +```python +secrets = { + 'ssid': 'Hackbots_Demo', + 'pw': 'Really_Insecure_Password!', + } +``` + +That's it just a simple [python dictionary][7] in a file! The beauty of this approach is that we can import this file (much like we did with the `html.py`) and access the settings easily, a brief example is shown below: + +```python +from secrets import secrets # This imports the `secrets.py` code as `secrets` into the current file +### We can then read the values into variables +### using the 'key' from the dictionary like so: +ssid = secrets['ssid'] +password = secrets['pw'] +``` + +Using this approach allows us to make changes to the configuration easily simply by changing the values in the dictionary and saving it to the device. which will help later on! + +Once we've saved our configuration and other files, pushed them to the [Pico W][2] we can visit the url (by default it's `http://192.168.4.1`) and we'll see the page we designed earlier all nice and pretty! + +Thanks for reading! - Stay tuned for part 3 where we'll go through the wiring up and building of the bot. +PW + +[1]: https://www.leighhack.org/blog/2024/the-hackbots-project/ "Original Hackbot Adventures" +[2]: https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html "Raspberry Pi Pico" +[3]: https://codepen.io/pen/ "CodePen" +[4]: https://paletton.com/ "Paletton" +[5]: https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals "Format Strings" +[6]: https://en.wikipedia.org/wiki/Don't_repeat_yourself "DRY programming" +[7]: https://docs.python.org/3/tutorial/datastructures.html#dictionaries "Python Dictionary" \ No newline at end of file diff --git a/content/blog/2024/large-storage-custom-nas/index.md b/content/blog/2024/large-storage-custom-nas/index.md index 6b6db13..7f065c8 100644 --- a/content/blog/2024/large-storage-custom-nas/index.md +++ b/content/blog/2024/large-storage-custom-nas/index.md @@ -39,6 +39,7 @@ If you open the large cover you find it has a location for 3 1/2 45 disks, see t {{< bimage src="images/IMG_2994.jpg" width="500" height="400" zone="60">}} + The drives sit in the grid and the vibration of the disks spinning is dampened by some rubber bands, you can see a couple in the picture. The drives are hot swappable and plug directly into a PCB, of which there are 9, each controlling 5 drives. The controller cards are actually just SATA port expanders, and in comparison to many port expanders work relatively well. @@ -85,6 +86,7 @@ We also have 3 of these {{< bimage src="images/IMG_3009.jpg" width="400" height="300" zone="30">}} + Nothing amazing, but simple 4 port SATA controllers. # Comparing drive sizes @@ -100,6 +102,7 @@ I created a 3d printed flat platform that the drives could stand on, just to tes {{< bimage src="images/IMG_2497.jpg" width="400" height="300" zone="30">}} + # Cabling At this point I realized the cabling would not fit under the platform, so any new location for the drives would either need to be custom with driver chip (like the previous items) or just connectors with drivers elsewhere, but also with the SSDs being smaller (hence shorter) there is now more room to move things upwards, as it turns out about 35mms of room. I then 3d printed a mask, that would allow me to use the nylong screws into the positions in the chassis but also allow me to add additional holes for anything I wanted to attach, so removing the need to match holes but allow me to extend upwards @@ -120,6 +123,7 @@ As it turns they are little rubbish. Not because they do not work, or that they {{< bimage src="images/IMG_3012.jpg" width="400" height="300" zone="30">}} + Then if you put it back with heat transfer epoxy, it will stop restarting, but remains incredibly slow! # Drive Connectors @@ -139,6 +143,7 @@ So in my wisdom I thought I could fit more connectors on the PCB, so I went for {{< bimage src="images/IMG_2752.jpg" width="400" height="300" zone="30">}} + So a completed PCB, it is a very simple design, two locations to power the drives and then pass through connectors for SATA {{< bgallery width="60" >}} @@ -153,6 +158,7 @@ It looks pretty, and did work, 20 drives and a boot drive, so 21 drives. {{< bimage src="images/IMG_2762 (1).jpg" width="400" height="300" zone="30">}} + At this point, which was quite a bit of work, I realized with much distress, it was slower than a snail, at one point I was getting an underwhelming 10Mb/s !!! # The current status @@ -186,6 +192,7 @@ To make the best use out of it you also need to expand the number of ports avail {{< bimage src="images/s-l1600 (2).jpg" width="400" height="300" zone="30">}} + It is an Intel RES2SV240 RAID card. It is not really a RAID card in this case, but provides 24 ports, of which 4 are inbound and 20 outbound. This card is relatvely good as you can then use SFF8087 cables to SATA ports, keeping the cabling manageable, rather than individual SATA cables So let's do the maths @@ -199,6 +206,7 @@ Even better the RES240 cards do not actually need to plug into the motherboard, {{< bimage src="images/s-l1600 (2).jpg" width="400" height="300" zone="30">}} + This is an amazing win so I started the build out as follows {{< bgallery width="80" >}} @@ -211,6 +219,7 @@ Add some drive location testing {{< bimage src="images/IMG_2883.jpg" width="400" height="300" zone="30">}} + It is brilliant what could go wrong! As it turns out ... there is always something! @@ -237,6 +246,7 @@ I am now going to do this {{< bimage src="images/IMG_2905.jpg" width="400" height="300" zone="30">}} + Instead of using the 9 locations for drives I am going for 6. The last 3 I can use for the RES240 cards and allow some space for cabling, air flow and as it turns out some boot space as well. In this picture you can see 84 drives, but I did mention 72, where did the other 12 come from ? Remember the 3 original controller cards, as it turns out they fit into the remaining PCI slots. @@ -247,6 +257,7 @@ We now end up with this {{< bimage src="images/IMG_2906.jpg" width="400" height="300" zone="30">}} + To show that it all works under Linux It does take about 4 minutes to boot though! @@ -542,4 +553,4 @@ Interesting things to note - the read IOPS was 21k and the write IOPS was 5k, th I need to add in the power pictures and some other things etc - \ No newline at end of file + diff --git a/content/blog/2024/lottery-winner-daisies/images/fusion_1.jpg b/content/blog/2024/lottery-winner-daisies/images/fusion_1.jpg new file mode 100644 index 0000000..122b467 Binary files /dev/null and b/content/blog/2024/lottery-winner-daisies/images/fusion_1.jpg differ diff --git a/content/blog/2024/lottery-winner-daisies/images/holding.jpg b/content/blog/2024/lottery-winner-daisies/images/holding.jpg new file mode 100644 index 0000000..35706de Binary files /dev/null and b/content/blog/2024/lottery-winner-daisies/images/holding.jpg differ diff --git a/content/blog/2024/lottery-winner-daisies/images/light_pack.jpg b/content/blog/2024/lottery-winner-daisies/images/light_pack.jpg new file mode 100644 index 0000000..ece39ae Binary files /dev/null and b/content/blog/2024/lottery-winner-daisies/images/light_pack.jpg differ diff --git a/content/blog/2024/lottery-winner-daisies/images/on_stage.jpg b/content/blog/2024/lottery-winner-daisies/images/on_stage.jpg new file mode 100644 index 0000000..6d41257 Binary files /dev/null and b/content/blog/2024/lottery-winner-daisies/images/on_stage.jpg differ diff --git a/content/blog/2024/lottery-winner-daisies/images/test_fit.jpg b/content/blog/2024/lottery-winner-daisies/images/test_fit.jpg new file mode 100644 index 0000000..b6d5ed2 Binary files /dev/null and b/content/blog/2024/lottery-winner-daisies/images/test_fit.jpg differ diff --git a/content/blog/2024/lottery-winner-daisies/index.md b/content/blog/2024/lottery-winner-daisies/index.md new file mode 100644 index 0000000..2410297 --- /dev/null +++ b/content/blog/2024/lottery-winner-daisies/index.md @@ -0,0 +1,75 @@ +--- +title: "Making Stage Props for the Lottery Winners" +subtitle: "" +date: 2024-06-23T07:40:38Z +tags: + - CNC + - Electronics + - Pi Pico +draft: false +author: Kian Ryan +author_email: kian@orangetentacle.co.uk +listing_image: images/on_stage.jpg +--- + +Before Christmas, a group of musicians walked in to the space to talk about designing stage props for their upcoming UK tour. + +Up front I'm going to be honest, I had briefly heard of the [Lottery Winners](https://www.thelotterywinners.co.uk/) but +had no sense of how big the band had become. [The Lottery Winners](https://en.wikipedia.org/wiki/The_Lottery_Winners) are a local band made good, with a Number 1 album - + [Anxiety Replacement Therapy](https://en.wikipedia.org/wiki/Anxiety_Replacement_Therapy), and had performed last year at Glastonbury. They're kind of a big deal. They asked if we +could make some stage props for them, giant daisies to be lit with stage lights for their Manchester O2 Apollo gig. + +We had been doing work with the CNC recently and I've made a few pieces for stage previously so agreed to draft up some ideas. +While the band focused on their tour, we worked on designing the props, working with their lighting designer to come up +with a design compatible with the lights that would be used on stage. + +{{< image src="images/fusion_1.jpg" title="Model design in Fusion 360" width="400x" class="is-pulled-left" >}} + +{{< image src="images/test_fit.jpg" title="Test fit on head and lighting stand" width="400x" class="is-pulled-right" >}} + +Using Fusion 360, we designed a model to be cut on our Shapeoko XXL, and performed some test cuts on 5mm acrylic. +The outer shape was cut from 5mm opaque white +and the inner shape from 3mm opaque yellow. They were bonded using Tensol 70. Using some generic angle brackets, we +tested the fit on the sample spot head and adjusted the design a bit, the band were happy with the design. + +{{< clearfix >}} + +{{< youtube UqzpV7Pt8ho >}} + + +Then the band asked if we could design a portable lighting pack to use on their other tour dates. + +We needed a one-size fits all solution. The same daisies would need to be used for all tour dates, so we needed a system +that would allow for switching between the portable packs, and the standing lamps. We agreed to use the same mounting +hardware - a lighting stand and angle bracket, and switch out the lighting for a portable USB powered LED system. We also +needed a system that could be easily charged on tour - regular LiPo battery packs USB charging were ideal, and could be +replaced on tour if needed. + +{{< image src="images/light_pack.jpg" title="Lighting Pack Light Ring and Mount" width="400x" class="is-pulled-left" >}} + +We used a [Plasma 2040 board from Pimoroni](https://shop.pimoroni.com/products/plasma-2040?variant=39410354847827) combined with [these WS2812B RGB rings from Cool Components](https://coolcomponents.co.uk/products/241-led-172mm-complete-ring-ws2812b-5050-rgb-led-with-integrated-drivers-adafruit-neopixel-compatible). We couldn't use all the rings, nor could we power all the LEDs at the same time, so with a bit of careful maths, we worked +out how many LEDs we could drive from the Plasma and the power supply. 3D printed housings in PETG were attached with magnets +to the back of a select number of the daisies, allowing the lighting packs to be attached and removed. + +Some simple Micropython allowed us to to design a few different lighting patterns controllable from the onboard buttons +of the Plasma 2040. I'm quite pleased with the results. + +{{< clearfix >}} + +{{< youtube EGnIsF4EzsA >}} + +For final stage dressing, and to hide cabling, we made green wrap sleeves sleeves for the lighting stands with hook and loop +closings and an over the top loop to hang from the top of the stand. + +These were shipped in two batches, first batch to the band on tour, and then a final delivery to the band at the +O2 Apollo Manchester. They very kindly offered us tickets to come and watch, and we made an evening to see the props and the band, +on stage. + +{{< clearfix >}} + +{{< image src="images/on_stage.jpg" title="Lottery Winners and Daisies on Stage in Manchester" class="middle" >}} + +Leigh Hackspace is open to commissions, and we're also keen on teaching people the skills to make for themselves. + +Our [Summer of Making]({{< ref "/blog/2024/summer-of-making/index.md" >}}), has a range of skills that can help get you started, or if +you have a project in mind, please [come and talk to us](mailto:directors@leighhack.org). \ No newline at end of file diff --git a/content/blog/2024/summer-of-making/images/summer_of_making.jpg b/content/blog/2024/summer-of-making/images/summer_of_making.jpg new file mode 100644 index 0000000..a210172 Binary files /dev/null and b/content/blog/2024/summer-of-making/images/summer_of_making.jpg differ diff --git a/content/blog/2024/summer-of-making/index.md b/content/blog/2024/summer-of-making/index.md new file mode 100644 index 0000000..9679852 --- /dev/null +++ b/content/blog/2024/summer-of-making/index.md @@ -0,0 +1,29 @@ +--- +title: "Summer of Making" +date: 2024-06-24T07:40:38Z +tags: + - Events + - Making + - Programme +draft: false +author: Kian Ryan +author_email: kian@orangetentacle.co.uk +listing_image: images/summer_of_making.jpg +--- + +{{< eventbrite >}} + +Alongside the opening of [Leigh Spinners Mill](https://www.spinnersmill.co.uk), [Leigh Hackspace](http://leighhack.org) +has launched our Summer Of Making programme of events open to members and non-members +from July to September. + +{{< image src="images/summer_of_making.jpg" title="Leigh Hackspace Summer of Making Flyer" width="400x" class="is-pulled-right" >}} + +We're offering the opportunity to try a new range of skills from 3d printing to garment making. + +Events are heavily discounted for [members]({{< ref "/membership/index.md" >}}), and members also +have access to the Hackspace for their own projects at other times. + +[You're welcome to visit for a chat or a tour.]({{< ref "/visit.md" >}}) + +If you have any questions, please [contact us](mailto:info@leighhack.org). diff --git a/content/blog/2024/the-hackbots-project/images/Wifi.png b/content/blog/2024/the-hackbots-project/images/Wifi.png new file mode 100644 index 0000000..cc738a3 Binary files /dev/null and b/content/blog/2024/the-hackbots-project/images/Wifi.png differ diff --git a/content/blog/2024/the-hackbots-project/images/basic_phone_to_bot_comms.png b/content/blog/2024/the-hackbots-project/images/basic_phone_to_bot_comms.png new file mode 100644 index 0000000..91a7cd9 Binary files /dev/null and b/content/blog/2024/the-hackbots-project/images/basic_phone_to_bot_comms.png differ diff --git a/content/blog/2024/the-hackbots-project/images/hackbot.jpg b/content/blog/2024/the-hackbots-project/images/hackbot.jpg new file mode 100644 index 0000000..4098aeb Binary files /dev/null and b/content/blog/2024/the-hackbots-project/images/hackbot.jpg differ diff --git a/content/blog/2024/the-hackbots-project/images/initial_schematic.png b/content/blog/2024/the-hackbots-project/images/initial_schematic.png new file mode 100644 index 0000000..57c1b85 Binary files /dev/null and b/content/blog/2024/the-hackbots-project/images/initial_schematic.png differ diff --git a/content/blog/2024/the-hackbots-project/index.md b/content/blog/2024/the-hackbots-project/index.md new file mode 100644 index 0000000..f33ef28 --- /dev/null +++ b/content/blog/2024/the-hackbots-project/index.md @@ -0,0 +1,268 @@ +--- +title: "The Hackbots Project" +subtitle: "Making Simple Robots That Anyone Can Build (Pt. 1)" +date: 2024-01-01T07:40:38Z +tags: + - Rasberry Pi Pico + - Robots + - Electronics +draft: false +author: Paul Williams +author_email: phyushin@gmail.com +listing_image: images/hackbot.jpg +--- + +## The Beginning +We'll start at the beginning, after all, it is the very best place to start! + +The inspiration for the robots came from wanting to make a simple project using fairly _off the shelf_ and _reasonably priced_ parts that young people could also get their hands on and follow allong with. + +_Note: This post has been written a little "after the fact" so some parts will be skipped... for brevity_ + +## The Prototype +The initial prototype used the following components +- [Raspberry Pi Pico][1] * 1 +- [L29XN Motor Controller][2] * 1 +- [DC motors][3] * 2 +- [Bluetooth Module][4] * 1 +- [Breadboard][5] * 1 +- A Piece of wood (to strap all the relevant bits too) +- A Caster (ideally, roughly the same size as the wheels attached to the DC motors) + +So, the initial idea was to connect up the Bluetooth Module to the Pico and read data coming _over_ bluetooth to send signals based on the data - if the _forward_ command was sent over bluetooth, call the _forward_ function, sounds super simple right? right! + +Below is an a code snippet of the functions (if you're following along i'd suggest having the [Github Repo][6] open in a different tab) + +```python +from machine import Pin,PWM,UART +import time + +uart= UART(0,9600) + +In1=Pin(6,Pin.OUT) #IN1 +In2=Pin(7,Pin.OUT) #IN2 +In3=Pin(4,Pin.OUT) #IN3 +In4=Pin(3,Pin.OUT) #IN4 + +EN_A=PWM(Pin(8)) +EN_B=PWM(Pin(2)) +# Defining frequency for enable pins +EN_A.freq(1500) +EN_B.freq(1500) + +# Set maximum duty cycle, well go with max speed for now! (0 to 65025) +EN_A.duty_u16(65025) +EN_B.duty_u16(65025) + +# Backward +def move_backward(): + print("Back up Back up") + In1.low() + In2.high() + In3.low() + In4.high() + +# Forward +def move_forward(): + print("Onwards!") + In1.high() + In2.low() + In3.high() + In4.low() + +# Stop +def stop(): + print("All Stop") + In1.low() + In2.low() + In3.low() + In4.low() + +while True: +if uart.any(): #Checking if data available + data=uart.read() #Getting data + data=str(data) #Converting bytes to str type + print(data) + if('forward' in data): + move_forward() #Forward + elif('backward' in data): + move_backward() #Backward +``` +Below is the initial schematic: + +{{}} + +As you can see above, this is roughly how the prototype fit together ... you connected to the bluetooth module, send the correct commands, the pico reads them over _[uart][7]_ and calls the respective functions... well that was the plan at least - it turns out that iOS devices don't work as _out of the box_ as android devices when it comes to serial over bluetooth shenanigans, so back to the drawing board on how we get the signals - after all it's no good to us if only some kids can use it! the idea was it could be done all by your phone. + +## MK II, III, and IV +So, now we've a relative idea of how it fits together we've got to overcome the issue of only being able to control robots using androids [is that meta?]. + +`MK II` we tried an ESP32 instead of the Pico and HC-05 combination... same issue it didn't like iOS devices :( . + +In `MK III` we tried to use a different bluetooth module with a bluetooth pad, but quickly felt that this process was a little too involved for the simple pick it up and play style we were going for. + +`MK IV`! we settled for replacing the Pico with a Pico W so that the wireless comms are all in the one (relatively cheap) package and instead of listening for serial commands over bluetooth; switched to using the WiFi that the Pico W has and created our very own web server, with the contols on it! - this has the added bonus of being able to customise the look [to some extent] as well as being _i-device_ compatible ... I'd call that a win! + +## MK IV Explained +With our Pico W wired in we needed to make some modifications to the program running on the Pico - thankfully most of it can stay the same - that's the handy thing about writing things in functions they're all nice and contained and you can just change the way you call them rather than reimplementing them. + +The main change is that instead of using bluetooth to communicate over serial we're now using the web server (this means upgrading to the Pico W for it's handy wireless functionality) to do the _talking_ and we just interact with _it_ + +Below is a very basic sequence diagram of how this works - did I mention it was basic? +{{}} + +Now that we've got the idea for how the communication works we can start to build the web _frontend_ for our bot... Keeping in mind that all the control functionality we already have from the `MK I` to `MK III` we just need to change the way the Pico [W now that we've _upgraded_] gets the instructions to _call_ the functions we need, we can think of this somewhat like the _frontend_ and _backend_ of any other web app really! + +### Connecting to the Pico W +So first things first; we need to configure the wireless functionality of our Pico W, I've opted to do this by using splitting this out into it's own file [secrets.py][8]. +An example `secrets.py` could be as follows: +```python +config = { + 'ssid': 'Hackbot', + 'pw': 'wonderful password' + } +``` + +By keeping the config _dictionary_ in a separate file we can add this file to our `.gitignore` to avoid checking in our password for our config, we can then read these config values with the following code + +```python +from secrets import config +# SNIP +# ... +ssid = config['ssid'] +password = config['pw'] +``` + +This would read the config files in to variables which our code can then _use_. + +_Note: You don't necessarily need to name the dictionary in `secrets.py` `config` ... you don't even need to name the file `secrets.py`!_ +_Just make sure what ever you name it is reflected in the `from import ` statement_ + +Now that we've got our config data into our main program file we can use this data to set up our Wifi access point on the Pico W, this is done by using code like: +```python +ap = network.WLAN(network.AP_IF) +ap.config(essid=ssid, password=password) +ap.active(True) + +while ap.active() == False: + pass + +print('Connection successful') +print(ap.ifconfig()) +``` +If your Pico is powered, you should now see it broadcasting an SSID like this: +{{ }} + +Fantastic! + +### Creating the Web App +The web application doesn't need to be anything fancy, after all we're going to just send get requests and read the URL for the direction. + +So, the initial webserver is created using a [socket][9] like so: + +```python +import socket +# SNIP +addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] +s = socket.socket() +s.bind(addr) +s.listen(1) + +``` + +This sets up a socket and begins _listening_; next, we need to create a webpage for it to _serve_. We can use python here too as it allows us to generate something a little more _dynamic_ later on; but for now, we'll just have the `generateHTML()` function return some static html: + + +```python +def generateHTML(): + return """ + + + Hackspace Bot + + + +
+
+ + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ """ + +``` + +Finally we want to set up a loop that parses data from the website requests to decide which direction to go in this is achieved like so: + +```python +while True: + try: + led.toggle() # this toggles the LED on the Pico on and off so we have some external sign that things are working + cl, addr = s.accept() + print('client connected from', addr) + request = cl.recv(1024) + data = str(request) + direction = (data[1:20].split(' ')[1].replace('/','')) # this extracts the direction from the _end_ of the url in the POST request. + + if(direction =='forwards'): + move_forward() + elif(direction == 'left'): + turn_left() + elif(direction == 'right'): + turn_right() + elif(direction == 'backwards'): + move_backward() + elif(direction == 'stop'): + stop() + + cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') + time.sleep(0.2) + cl.send(generateHTML()) + cl.close() +``` + +What the above code does is accepts connections from clients (`cl`) of the Wifi access point and sends the control web page to them... from there, users issue commands via the buttons on the webform. + +The whole project code is available on the [Github repo][6] + +Thanks for reading! + +[1]: https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html "Raspberry Pi Pico Family" +[2]: https://components101.com/modules/l293n-motor-driver-module "L29xN Motor Controller" +[3]: https://www.amazon.co.uk/dp/B07VBXXT9M/ref=cm_sw_r_api_i_BB50HXYKHPBAT04PZ3PT_0 "DC Motors" +[4]: https://components101.com/wireless/hc-05-bluetooth-module "HC-05 Bluetooth Module" +[5]: https://www.ebay.co.uk/itm/203599232851 "Solderless breadboard" +[6]: https://github.com/leigh-hackspace/hackspace-bots "Project Code" +[7]: https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter "UART" +[8]: https://github.com/leigh-hackspace/hackspace-bots/blob/main/example_secrets.py" "Secrets.py" +[9]: "https://docs.python.org/3/library/socket.html" "Python Sockets" \ No newline at end of file diff --git a/content/membership/index.md b/content/membership/index.md index a9564c8..a11e29a 100644 --- a/content/membership/index.md +++ b/content/membership/index.md @@ -14,4 +14,4 @@ Being a member is being part of a social making and learning community. Our memb We suggest that you [visit the hackspace]({{< ref "/visit" >}}) in person before you commit to be a member. This will allow you to see the space, understand what is available, and how it can work for you. We have further information on our [wiki](https://wiki.leighhack.org/membership/joining/). -All memberships are collected on the 1st of the month, but if you wish to arrange an alternative date then please [contact us](mailto:info@leighhack.org). \ No newline at end of file +All memberships are collected within 5 working days of signing up, but if you wish to arrange an alternative date then please [contact us](mailto:info@leighhack.org). \ No newline at end of file diff --git a/layouts/page/calendar.html b/layouts/page/calendar.html index eb09729..670a206 100644 --- a/layouts/page/calendar.html +++ b/layouts/page/calendar.html @@ -11,13 +11,13 @@ {{ end }} {{ define "extra_js" }} - + {{ $js := resources.Get "js/calendar.js" | resources.Minify }} {{ $secureJS := $js | resources.Fingerprint "sha512" }} {{ end }} {{ define "content" }} -
+

Your browser doesn't support (or has disabled) Javascript. If you wish to see the upcoming event calendar you can use our iCal Feed with your calendar or mail software.

{{ printf "" ("/cgi/events.cgi" | relURL) | safeHTML }} {{ end }} \ No newline at end of file diff --git a/themes/lhs-retro/layouts/blog/list.html b/themes/lhs-retro/layouts/blog/list.html index 3ee9908..664e57f 100644 --- a/themes/lhs-retro/layouts/blog/list.html +++ b/themes/lhs-retro/layouts/blog/list.html @@ -21,7 +21,7 @@
- +

{{.Title}} - {{ .Params.author }}
diff --git a/themes/lhs-retro/layouts/blog/single.html b/themes/lhs-retro/layouts/blog/single.html index 4f0a475..de65bc4 100644 --- a/themes/lhs-retro/layouts/blog/single.html +++ b/themes/lhs-retro/layouts/blog/single.html @@ -16,8 +16,10 @@ {{ .Params.author }}'s avatar

-

This is a post by {{ .Params.author }}.
Originally - posted {{ .PublishDate | time.Format ":date_full" }}

+

This is a post by {{ .Params.author }}.
Posted {{ .PublishDate | time.Format ":date_full" }}
+ {{ if .Params.original_url }}
Originally posted at {{ + .Params.original_url }}{{ end }} +

diff --git a/themes/lhs-retro/layouts/partials/header.html b/themes/lhs-retro/layouts/partials/header.html index a9dea56..9fead77 100644 --- a/themes/lhs-retro/layouts/partials/header.html +++ b/themes/lhs-retro/layouts/partials/header.html @@ -1,5 +1,5 @@ {{ with resources.Get "images/rose_logo.gif" }} -

The logo of Leigh Hackspace Leigh +

The logo of Leigh Hackspace Leigh Hackspace

{{ end }}

diff --git a/themes/lhs/archetypes/blog/index.md b/themes/lhs/archetypes/blog/index.md index d8a6974..d56f82a 100644 --- a/themes/lhs/archetypes/blog/index.md +++ b/themes/lhs/archetypes/blog/index.md @@ -4,6 +4,8 @@ subtitle: "" date: {{ .Date }} tags: [] draft: true -author: +author: # Name to show on the post author_email: # used for Gravatar icon +listing_image: # Image to use in the post list on the website +original_url: # If cross-posted from a blog, link to the original. --- diff --git a/themes/lhs/assets/sass/leighhack.scss b/themes/lhs/assets/sass/leighhack.scss index b970fad..fc43f96 100644 --- a/themes/lhs/assets/sass/leighhack.scss +++ b/themes/lhs/assets/sass/leighhack.scss @@ -6,7 +6,7 @@ src: url('../fonts/transport-medium.woff2') format('woff2'); } -// Hackspace Branding +// Hackspace Branding //$family-sans-serif: "Roboto", sans-serif; $primary: #d41246; $accent: #fbf3ee; @@ -92,7 +92,7 @@ p { } // ------------------------------------------------------- -// Base +// Base // ------------------------------------------------------- a { text-decoration: underline; @@ -315,7 +315,7 @@ address { } // ------------------------------------------------------- -// Footer +// Footer // ------------------------------------------------------- footer { @@ -368,4 +368,20 @@ footer { // Fix syntax highlighting to match Bulma pre div.highlight { padding-bottom: 1.25em; +} + +// Hackspace Status +div#hackspace-open { + display: none; +} + +.events { +background-image: linear-gradient(red, orange); + a { + color: white; + } + border: 2px solid red; + border-radius: 5px;; + padding: 2rem 0; + margin-bottom: 2rem; } \ No newline at end of file diff --git a/themes/lhs/layouts/_default/baseof.html b/themes/lhs/layouts/_default/baseof.html index 3ae205f..73a7eed 100644 --- a/themes/lhs/layouts/_default/baseof.html +++ b/themes/lhs/layouts/_default/baseof.html @@ -30,7 +30,7 @@

{{ block "hero-image" . }} {{ $hero := printf "%s/%s" "images/" .Params.hero_image }} - + {{ end }}
{{ end }} @@ -48,10 +48,10 @@ {{ block "content" . }} {{ end }} + +
-
- {{ block "cta" . }} {{ if (default true .Params.show_cta) }} {{ if .Params.show_big_cta }} diff --git a/themes/lhs/layouts/blog/list.html b/themes/lhs/layouts/blog/list.html index 7dcd188..280aab0 100644 --- a/themes/lhs/layouts/blog/list.html +++ b/themes/lhs/layouts/blog/list.html @@ -15,12 +15,14 @@

{{ .Key }}

{{- range .Pages }} -{{ $image := .Resources.GetMatch .Params.listing_image }} -{{ $image = $image.Fill "512x512 Center jpg" }}
- + {{ with .Resources.GetMatch .Params.listing_image }} + {{ $image := . }} + {{ $image = $image.Fill "512x512 Center jpg" }} + + {{ end }}

{{.Title}} - {{ .Params.author }}
@@ -32,4 +34,4 @@

{{- end }} {{- end }} -{{ end }} \ No newline at end of file +{{ end }} diff --git a/themes/lhs/layouts/blog/single.html b/themes/lhs/layouts/blog/single.html index 8183b5f..760fcb0 100644 --- a/themes/lhs/layouts/blog/single.html +++ b/themes/lhs/layouts/blog/single.html @@ -17,8 +17,10 @@
-

This is a post by {{ .Params.author }}.
Originally - posted {{ .PublishDate | time.Format ":date_full" }}

+

This is a post by {{ .Params.author }}.
+ Posted {{ .PublishDate | time.Format ":date_full" }} + {{ if .Params.original_url }}
Originally posted at {{ .Params.original_url }}{{ end }} +

diff --git a/themes/lhs/layouts/partials/design/bigcta.html b/themes/lhs/layouts/partials/design/bigcta.html index 7eb7d90..0e04e0f 100644 --- a/themes/lhs/layouts/partials/design/bigcta.html +++ b/themes/lhs/layouts/partials/design/bigcta.html @@ -3,7 +3,7 @@
- +
diff --git a/themes/lhs/layouts/partials/design/cta.html b/themes/lhs/layouts/partials/design/cta.html index 46835a4..ecbe2a5 100644 --- a/themes/lhs/layouts/partials/design/cta.html +++ b/themes/lhs/layouts/partials/design/cta.html @@ -1,8 +1,8 @@
-
- Leigh Hackspace is open to all.
Being a member gives you access to our space, tools, and community. +
+

Leigh Hackspace is open to all.
Being a member gives you access to our space, tools, and community.

Join Leigh Hackspace diff --git a/themes/lhs/layouts/partials/footer.html b/themes/lhs/layouts/partials/footer.html index 43c3782..222d3ec 100644 --- a/themes/lhs/layouts/partials/footer.html +++ b/themes/lhs/layouts/partials/footer.html @@ -2,7 +2,7 @@
- The logo of Leigh Hackspace + The logo of Leigh Hackspace
diff --git a/themes/lhs/layouts/partials/header.html b/themes/lhs/layouts/partials/header.html index 54342df..16086cf 100644 --- a/themes/lhs/layouts/partials/header.html +++ b/themes/lhs/layouts/partials/header.html @@ -1,12 +1,11 @@ -