03 April, 2022

Challenging myself to learn something new

I have recently set a big challenge for myself. I want to know about Machine Learning. To add to the challenge, I am trying out using the Zettelkasten method. The tool that I am using is Obsidian.

What is Zettelkasten?

It is a system for note-taking and personal knowledge management. From my reading, it looks like students and authors could use this method to help them organize their thoughts, make connections between thoughts, and turn those thoughts into written communication like term papers, doctoral thesis, books, or blog posts.

The heart of the system is to make a note that is focused on one topic, self-contained (no other explanation needed), permanent, concise, and linked to another note or notes.

Why am I look at Zettelkasten?

My current job requires me to read about various technologies and think about how to apply that technology to a business problem. I am hoping that Zettelkasten method can help me manage what I already know, acquire new knowledge, and make connections between the knowledge.

At work, the team and I make use of a shared Microsoft OneNote. Over the last 3 years, this notebook has grown rather large. It can be hard to find information using just a search. I have read that there are people who have figured out how to use Zettelkasten with OneNote. I need to learn a bit more about the method before I can teach it to someone else.

Why use Obsidian?

I picked Obsidian because it is cross-platform, free, looks simple to use, and looks a bit like Visual Studio Code. In learning about the tool there additional benefits became apparent. Obsidian makes use of Markdown. If I wanted I could switch to using a different tool to create and edit the markdown files. Backing up a markdown file is easy. The community has created a large number of plugins to help customize Obsidian and add functionality.

Why Machine Learning?

Mostly because I like to learn. This is an area that I know very little about. It seems to me that one aspect of machine learning known as Deep Learning could help me learn more.

There is an article from Stanford entitled "Deep learning algorithm does as well as dermatologists in identifying skin cancer" that shows the potential good deep learning has to offer.

References

  1. Machine Learning
  2. Zettelkasten
  3. Obsidian
  4. Microsoft OneNote
  5. Markdown
  6. Deep Learning
  7. Deep learning algorithm does as well as dermatologists in identifying skin cancer

26 September, 2020

Back to learning about Docker

A few months ago, I started learning about Docker. I got derailed with work projects and personal projects. Now that I have a bit of time, I want to get back to learning about Docker. 
I came across the book "Learn Docker in a Month of Lunches" by Elton Stoneman. Elton is putting a YouTube video each workday.

Day 1 - Understanding Docker and running Hello, World

Docker Commands covered in "Learn Docker in a Month of Lunches: Day 1"
  • docker version
  • docker-compose version
  • docker container run {name of image}
  • docker container run --interactive --tty {name of a image}
  • docker container ls
  • docker container top {container id}
  • docker container logs {container id}
  • docker container inspect {container id}
  • docker container ls --all
  • docker container run --detach --publish {local port:container port} {name of a image}
  • docker container status {container id}
  • docker container rm --force $(docker container ls --all --quite)

Notes from Day 1

  • The Docker Engine is the thing that runs the containers.
  • Container wraps the application and has resources that the container can access.
  • Containers are like a virtual environment in concept. One major difference is the container relies on the hosting machine's resources.
  • Containers stop automatically when the code in the container stops.
  • The Docker CLI can be configured to run against a local docker server or against a remote docker server

Day 2 - Building your own Docker images

Docker Commands covered in "Learn Docker in a Month of Lunches: 02"
  • docker image pull {name of image}
  • docker container run -d --name {name I want the container called} {name of image}
  • docker container logs {name of image}
  • docker container -rm {name of image}
  • docker container run --end {key=value pair} {name of image}
  • docker image build --tag {name} .
  • docker image ls
  • docker image history {image name}
  • docker system df

Notes from Day 2

  • Dockerfile contains the steps needed to build a Docker image. This kind of like install instructions or a runbook.
  • Docker commands follow a pattern
    • docker {command} {subcommand} - with Docker 1.13 the CLI was restructured
  • We talk about an image as a singular thing. An image is built up of many layers or parts. The images parts can be shared among other images.
  • Dockerfile
    • Dockerfile commands are capitalized (ie FROM, ENV, WORKDIR)
    • FROM line is required and is first-line
    • WORKDIR creates a working directory
    • CMD is the startup command for a container
  • The size listed from the command 'docker image ls' is the logical size.
  • A good practice is to structure the Dockerfile in such a way that the cache is used. This helps reduce the amount of time it takes to rebuild an image. 
    • The build process creates a hash for each step in the Dockerfile. This hash is used to help determine if that step needs to be rebuilt. Once the build encounters a step that needs to be rebuilt then all steps from that point to the last step will be rebuilt.
    • Put the commands that are least likely to change first

Day 3 - Packaging apps from source code into Docker images


Docker commands covered in "Learn Docker in a Month of Lunches: 03"
  • docker image build -t { name of image } .
  • docker container run { name of image }
  • docker network create { name of network }
  • docker container run --name { name of container} -d -p { host port }:{ container port } --network { name of network } { name of image }docker co
  • docker image ls -f reference={first image} -f reference={second image}
  • docker system prune

Notes from Day 3

  • Able to run commands inside Dockerfile
    • examples would be expanding zip files, running Windows installers, running a git command
  • Dockerfile can contain multi-stages
    • the final stage should contain only what is needed to run the application
    • the image size can change while the image is building
  • With Docker, it is possible to build an image from source code without having an SDK installed
  • Dockerfile
    • EXPOSE - port the container should listen on
  • Multistage Dockerfiles are important and useful
    • Helps standardize your project across various OS
    • Helps standardize processes across projects. Any project using a Dockerfile basically need two commands to get the project running
      • docker image build
      • docker container run
    • The use of layers within an image reduces the amount of time spent in rebuilding images
      • The first time an image is built all the layers need to be pulled, processed, and cached. After the first build, the cached layers can be used.
        • The order of the commands in the Dockerfile is important
      • The use of layers and cache comes at the expensive of hard drive space
        • Docker doesn't auto clean the cache
    • Separates the build & package tools from what is needed for deployment
  • Within a multistage Dockerfile, the steps in each stage should be organized so the steps change slowly or whose results are not like to change goes first.
    • You can only optimize so far. If one step relies on the results of a previous step then the steps must appear in that order.
      • An example would be the run command 


Resources





Fighting with the first layer

Recently, three events happened in a row that is leaving me with the problem of getting the first layer of my 3D prints to stick. The PLA filament that I was using ran out. An update to OctoPrint went sour, resulting in a rebuild. Lastly, I updated the version Cura I am using. 

I have tried several ways to get the print to stick. First was flipping the glass bed over. I have gone through the bed leveling process (both manual and automatic) several times. According to Bed Visualizer, I am close. In Cura, I have tweaked the 'Initial Layer Height' to 0.1 and the 'Build Plate Temperature' to 65C. The results I have gotten so far are either the filament doesn't stick or after a few layers, the edges start to curl and pull away from the bed. 

My next set of changes involved using a glue stick and switching from a skirt to a brim. I was able to get a 'CHEP Calibration Cube' to print. The print popped right of the bed. Closer inspection of the print revealed that the first layer is under extruded and the edges of the print pulled away from the bed. The top of the print (last layer) looks like the nozzle dig in a little (over extrusion).

I compared the latest print to prints from the previous roll of filament. The first layer on the previous filament is much thicker.

Possible Options

  • Make sure the bed is level
    • Good prints start with a level bed. 
    • Did this 4 times earlier in the day
  • Reduce the print speed for the first layer
    • It idea behind the slower print speed is to give the filament time to flow out of the nozzle into place and harden.
    • the current setting is 25 mm/s. This seems reasonable speed. I will skip with option
  • Increase the height of the first layer 
    • From what I have read, increasing the initial layer height can reduce the backpressure on the filament which should let the filament flow out a little easier.
  • Increase the extrusion amount for the first layer
    • This should force a bit more filament out. There is a possibility of the print suffering from an elephant's foot. It could also increase the backpressure on the filament.
  • Increase the extruder temperature
    • A little more heat could allow the filament to flow a little easier. 
  • Check the filament diameter setting
    • The filament size is 1.75 in the settings. 
    • Checked the nozzle diameter at the same time. 

Setting up for the next test print

Reprinting the CHEP Calibration Cube. Changed the initial layer height from 0.1 to 0.12. Changed printing temperature from 195C to 200C. Used the glue stick on the bed. 

Results

The print stuck to the bed a lot better. The first layer doesn't have as many defects and imperfections. I can clearly see a space between each line the makes up the first layer. This looks under extruded.

It seems this filament like the 200C. 

Setting up for the next test print

Reprinting the CHEP Calibration Cube. Changed the initial layer height from 0.12 to 0.18. Used the glue stick again. 

Results

There is even less under extrusion with the first layer. 

Setting up for the next test print

This time, I going to print the CHEP Calibration Cube, one of the tolerance tests from Makers Muse, and a few models of my own design (drop ceiling clip). Changed the initial layer height from 0.18 to 0.20. Changed from brim to skirt. Used the glue stick on the bed.

Results

I canceled the print just as the 3rd layer was starting. One of the models was not sticking to the bed. The first layer is under extruded. 

Setting up for the next test print

Just printing the CHEP Calibration Cube. Changed the initial layer flow from 100% to 102%. Wiped the bed down with Isopropyl Alcohol. Used the glue stick.

Results

The print was really stuck down. I have to use a putty knife to get the print free. The individual lines that make up the first layer are a little fatter and there is still a bit of space between the lines. 

Wrap up

This turned out to be a good learning experience. The lesson of a 'level bed is the starting point' was re-enforced. I learned that the distance between the 'bed and the nozzle', 'how fast the material flows out of the nozzle', and 'type of bed surface' all impact each other.  


18 September, 2020

OctoPrint Reinstall

From the OctoPrint web site, I downloaded a new version of OctoPi 0.17.0 image. Used gparted to wipe out all the partitions on an SD card. Next came flashing the OctoPi image to the SD card using Etcher.

Modified the octopi-wpa-supplicant.txt on the boot drive with my network credentials and modified the country info

After placing the SD card back in the Pi, I powered the device up and waited 5 minutes. I found the IP address of the Pi then opened a terminal window and started an SSH session to the Pi. 

From the command line on the Pi, I ran the command 'sudo raspi-config'. I changed the Password, changed the Timezone, and updated to the latest version. For good measure, I rebooted the Pi.

Once OctoPi was up and running, I opened the URL to the local version of OctoPi, I went through the standard setup screens. After another few minutes, I was prompted to updated OctoPrint to 1.4.2.

Once the OctoPrint finished updating to the latest version and rebooted. It was time to get some plugins.

Plugins

  • Bed Visualizer
    • Ran multiple times and made small adjustments between each run. 
  • EEPROM Marlin Editor
  • Navbar Temp
  • Octolapse 
    • Starting off with this disabled. I will need to come back later to config and enable. 
  • Octoslack 
  • Themeify
    •  Applied the settings from Teaching Tech
    • Added a new style. Selector '.navbar-text', CSS-Rule 'color' Value '#667cea'
  •  
In Cura, set up a connection to OctoPrint. The set up is found in Preferences -> Printers -> Select the printer -> Connect OctoPrint button.

 


14 September, 2020

Upgrade to Cura 4.7.1 and Upgrade of OctoPrint to Python3

Cura

Today, I made the jump from Cura 4.62 to Cura 4.7.1. In reviewing the release notes, for Cura 4.7.0 there were a lot of updates. I should have updated to Cura 4.7.0 earlier. 

There are some items in Cura 4.7.0 that I am looking forward to playing with or will make using the tool a little easier. 

  • Rotation widgets
  • Moved tree-support from experimental to normal settings
  • Adjust initial layer horizontal expansion
  • Allow a g-code to be inserted before or after pausing
Cura 4.7.1 contains a small list of bug fixes. 
 

OctoPrint

When I fired up OctoPrint today, I was greeted with the notice 'Upgrade your OctoPrint install to Python3!' After reading the blog post, I couldn't see a reason not to update. I open a SSH session to my Rasberry PI running OctoPrint and ran the commands from the article. It took a bit of time for everything to download and install.

There are some messages from the updated that will need to be researched or addressed at a later day. 

After rebooting the Raspberry Pi, I am now getting a message that 'The OctoPrint server is currently not running'. When I SSH to the Raspberry Pi, the message 'OctoPrint version : unknown' and 'OctoPi version : 0.17.0' is now displaying.

After a bit of thought, I am just going to rebuild the OctoPrint installation.

13 September, 2020

Updating the version of Docker on my primary machine

I noticed that the version of Docker that I am running a little behind the current stable version. I am thinking it is time to update.

After reading the 'Install Docker Engine on Ubuntu' page, I needed to make a few changes to my system.

My first step was to remove the source 'https://download.docker.com/linux/ubuntu disco stable' from sources. It was simple to follow the steps.

Ran the following commands

  • sudo apt-get remove docker docker-engine docker.io containerd runc
    • This made sure that any older versions were removed from my computer.
  • sudo apt-get update
  • sudo apt-get install \
        apt-transport-https \
        ca-certificates \
        curl \
        gnupg-agent \
        software-properties-common
    • This allows apt to use a repository over HTTPS
  • curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
    • Added the Docker's GPG key
  • sudo apt-key fingerprint 0EBFCD88
    • Verifies that I have key with the correct fingerprint
  • sudo add-apt-repository \
       "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
       $(lsb_release -cs) \
       stable"
    • setup a the stable repository
  • sudo apt-get update
  • sudo apt-get install docker-ce docker-ce-cli containerd.io
    • installed the latest version of Docker Engine and containerd

08 August, 2020

Trouble with updating version of GO on my Linux box

I had a little trouble with updating my version of GO. 

I started running the following commands

sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.14.7.linux-amd64.tar.gz

Now I should be done and ready. When I ran

go version

the old version number was reported. This is strange. My solution was to run the commands

which go
whereis go

to find out where GO was being referenced. After deleting all the references I was finally able to install the new version.


02 August, 2020

Comparing Cura profiles

Today, I want to test the differences between the Cura 'Standard Quality' profile and Chuck Hellebuyck's profile 'Cura for Creality Printers'.

Plan

  • Load the build plate with a few simple models.
  • Slice with the default 'Standard Quality' profile.
  • Print the models
  • Slice with CHEPV4.6.x_0.20(Good) profile
  • Print the model
  • Compare results

Actual

  • Room
    • 22C
    • Humidity 52

Run 1 - Standard Quality

  • Preheat the hot end to 190C
  • Preheat the bed to 70C
  • Note: Took about minutes to get the hot end and bed to temperature.
  • Slice the models
    • Estimates 
      • time 1 hours 17 minutes
      • material PLA 10g - 3.34 m
    • hot end to 200C
    • bed to 60C
    • Notes: Cura gave warning about the model not being manifold. 
  • OctoPrint 
    • estimates a time of 50 minutes
    • Octolapse running
  • End of run 1 notes
    • Lots of blobs, zits, and stringing when the hot end moves away for a picture.
    • Little stringing between objects
    • Print Time
      • OctoPrint 1:25:21
      • Cura with OcotoPrint connection 1:25:21
      • Slack notifications 1:25
    • Raspberry Pi temperature ranged from 38C to 40C
    • No noticeable lifting of the model from the bed
    • skirt pulled away from the bed easily, Measured skirt thickness at several places. Values ranged from .19mm to .23mm.
    • Models popped off the bed with just finger strength. 
      • EasyCalib3.stl
        • slight rounding of the corners of the base.
        • little z banding


      • TESTBLOKJE.STL
        • blobs from where the hot end moved away from the model. Most noticeable blobs were pointing in the direction the hot end moves away for Octolapse to take a picture. 


      • OpenRC_Calibration_Cube.stl
        • The M3 nuts I have did not fit the holes. The holes are just too small. 
        • Some blobs from Octolaspe


      • CHEPCalibrationCube.stl
        • Some blobs from Octolaspe 
        • X face - 20.01 to 20.42
        • Y face - 20.10 to 20.34
        • Z face - 19.95 to 20.24


Run 2 - CHEPV4.6x_0.20(Good)

  • Preheat the hot end to 190C
  • Preheat the bed to 70C
  • Slice the model 
    • Estimates
      • time 1 hour 39 minutes
      • material PLS 13g - 4.29m
  • OctoPrint
    • estimates 1 hour
    • Octolapse running
  • End of run 2 notes
    • Lots of blobs, zits, and stringing when the hot end moves away for a picture. The amount of artifacts seems lower. 
    • Almost no stringing between objects. 
    • Print Time
      • OctoPrint 1:42:52
      • Cura with OcotoPrint connection 1:42:52
      • Slack notifications 1:42
    • Raspberry Pi temperature ranged from 39C to 42C
    • No noticeable lifting of the model from the bed
    • skirt pulled away from the bed easily, Measured skirt thickness at several places. Values ranged from .17mm to .22mm.
    • Models popped off the bed with just finger strength. 
      • EasyCalib3.stl
        • No Z banding


      • TESTBLOKJE.STL
        • very similar to run 1.
        • more blobs on the pyramid


      • OpenRC_Calibration_Cube.stl
        • I was able to fit a nut into a few but not all of the holes and slots.


      • CHEPCalibrationCube.stl
        • x face - 20.0 to 20.35
        • y face - 20.01 to 20.25
        • z face - 19.95 to 20.20





Resources

  • walls are exact 1.0mm to see eventual over- or underflow
  • a little 45° overhang with a 1.0mm platform that shows warping and if you probably need to change the filament-fan speed
  • stringing in the tube or between tube and platform
  • a 0.2mm space between the cube and the cylinder to check with a paper if needed
OpenRC Calibration Cube (OpenRC_Calibration_Cube.stl)
  • M3 nuts should fit    
CHEP Calibration Cube (CHEPCalibrationCube.stl)
  • 20mm by 20mm by 20mm

25 July, 2020

Upgrade to Cura 4.6.2

Today, I upgraded my version of Cura to 4.6.2. 

After reviewing the release notes, there was no reason for me to upgrade to this version other than the habit of trying to keep the software current. 

Updating the starting and ending G-code

Today, I am making some minor tweaks to the start and end G-code within Cura. There are three changes I would like to make. The first is to have the bed and the hot-end heat up at the same time. Second, I am wondering if calling M420 right after a G29 is helpful. If it is not helpful then come up with helpful solution. The third change is to have the hot-end to have a different ending position.

Final G-code

Start G-code

M201 X500.00 Y500.00 Z100.00 E5000.00 ;Setup machine max acceleration
M203 X500.00 Y500.00 Z10.00 E50.00 ;Setup machine max feedrate
M204 P500.00 R1000.00 T500.00 ;Setup Print/Retract/Travel acceleration
M205 X8.00 Y8.00 Z0.40 E5.00 ;Setup Jerk
M220 S100 ;Reset Feedrate
M221 S100 ;Reset Flowrate

; Start Dual Nozzle/Bed Preheating
M140 S{material_bed_temperature_layer_0} ; start preheating the bed
M104 S{material_print_temperature_layer_0} T0 ; start preheating hotend
G28 ; home
M190 S{material_bed_temperature_layer_0} ; heat to Cura Bed setting 
M109 S{material_print_temperature_layer_0} T0 ; heat to Cura Hotend

G28 ;Home
G29 ;
M500 ; Save settings

G92 E0 ;Reset Extruder
G1 Z2.0 F3000 ;Move Z Axis up
G1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position
G1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line
G1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little
G1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line
G92 E0 ;Reset Extruder
G1 Z2.0 F3000 ;Move Z Axis up 

End G-code

G91 ;Relative positioning
G1 E-2 F2700 ;Retract a bit
G1 E-2 Z0.2 F2400 ;Retract and raise Z
G1 X5 Y5 F3000 ;Wipe out
G1 Z10 ;Raise Z more
G90 ;Absolute positionning

G1 X{machine_width} Y{machine_depth} ;Present print
M106 S0 ;Turn-off fan
M104 S0 ;Turn-off hotend
M140 S0 ;Turn-off bed

M84 X Y E ;Disable all steppers but Z

Research 


Change 1

Chuck Hellebuyck has a video on how to get Cura to heat up the bed and hot end at the same time. Faster Hot End & Heated Bed warm-up in Cura

Change 2

G29 - Bed Leveling (Automatic): Probes the bed and enables bed leveling compensation.
M420 - Bed Leveling State: Get and/or set bed leveling state.
M500 - Save Setting: saves all configurable settings to EEPROM

Having a start g-code that uses a G29 followed by M420, is not necessary. The G29 turns on bed leveling, probes the bed, and stores the values to RAM. The M420 turns on bed leveling and reads the values from the EEPROM. 

Options to make bed leveling more helpful
  1. Modify the start g-code to run G29 without M420
  2. Modify the start g-code to run G29 and M500 without M420
  3. Modify the start g-code to run G29, M500, and M420
  4. Modify the start g-code to run M420 and occasionally run a bed leveling that saves the data

In thinking through the options, I have settled on option 2. The build surface on my Ender 5 Plus is removable. Having the auto-leveling routine run before each print should help get a good first layer as the build surface develops imperfections over time. By saving the bed leveling data, I should get two benefits. The first benefit is the data will be present after the power is cycled on the printer. The second benefit is the plug-in 'Bed Visualizer' will have current data. 

Change 3

The ending G-code uses the variable {machine_depth} to set the 'Y' axis. This puts the hot end in the back left corner. The problem is when the printer starts up the BL Touch sensor reports an error. My solution is to change from using the variable {machine_depth} to a value of '0'. 

Update: The X0 Y0 position put the hot end in the front left corner. I am trying X{machine_width} y{machine_depth}, hopefully this puts the hot end in the back right corner. 

Before Changes

Before I get started on making any changes, I recorded the start and end G-code that my version of Cura (4.6.1) is using.

Start G-code

M201 X500.00 Y500.00 Z100.00 E5000.00 ;Setup machine max acceleration 
M203 X500.00 Y500.00 Z10.00 E50.00 ;Setup machine max feedrate 
M204 P500.00 R1000.00 T500.00 ;Setup Print/Retract/Travel acceleration 
M205 X8.00 Y8.00 Z0.40 E5.00 ;Setup Jerk 
M220 S100 ;Reset Feedrate 
M221 S100 ;Reset Flowrate 

G28 ;Home 
G29 ; 
M420 S1 Z2 ;Enable ABL using saved Mesh and Fade Height 

G92 E0 ;Reset Extruder 
G1 Z2.0 F3000 ;Move Z Axis up 
G1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position 
G1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line 
G1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little 
G1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line 
G92 E0 ;Reset Extruder G1 Z2.0 F3000 ;Move Z Axis up 

End G-code

G91 ;Relative positioning
G1 E-2 F2700 ;Retract a bit
G1 E-2 Z0.2 F2400 ;Retract and raise Z
G1 X5 Y5 F3000 ;Wipe out
G1 Z10 ;Raise Z more
G90 ;Absolute positionning

G1 X0 Y{machine_depth} ;Present print
M106 S0 ;Turn-off fan
M104 S0 ;Turn-off hotend
M140 S0 ;Turn-off bed

M84 X Y E ;Disable all steppers but Z 


04 July, 2020

Getting the first layer right

Over the past few days, I have made several attempts to level the bed of my Ender 5 Plus. I have read the manual that came with the printer, read several forums, and watched several YouTube videos. 

What I have learned
  • The first layer is very important to get right. This is the foundation that the rest of the print is built on. 
  • If a print has trouble sticking to the bed. Check the bed level is a good first step.
  • The OctoPrint plugin Bed Visualizer can help understand where there are high spots and low spots on the build plate.
  • There is the "right" amount of squish. See 'Bed Leveling Guide' image. 

I am using the model 'Bed Leveling Calibration Test Object (Parametric)' by pgreendland. The first couple of attempts turned out poorly. This caused me to relevel the bed. In looking closer at the results, I could clearly see each line the printer laid down. This got me to thinking that maybe under extrusion was the problem. I did switch some part on the extruder motor. I wanted metal parts instead of plastic. 

I performed the standard extrusion test. The hot end was heated to 200 C, I marked the filament at the 100 and 110 mm points, and extruded 100 mm. Only 94 mm of the filament was pulled in. 

To update the extruder steps, I made a back of the configuration using the OctoPrint plugin 'EEPROM Marlin Plugin'.  For my printer, the Extruder steps were 94. Using the formula (expected amount of filament * Current E-Steps) / Actual extrusion amount, I was able to calculate a new step value. 

(100 X 93) / 94 = 98.9

I set and saved the new value to the EEPROM then reran the extrusion test. This time the test hit the mark. 

Reprinting of the 'Bed Leveling Calibration Test Object' turned out better. The print stuck to the bed. The print was not as solid as I expected. I also think that the hot end may be a little high. 

For the next test, I am going with a more complex model. I am not changing any settings. I want to see if the current settings can produce a nice print. I am going with the 'CHEP Calibration Cube' for the model. 



Setting up Octoprint

When I was running my old 3D printer, I found using OctoPrint to be helpful. I think it would be good to set up a new instance of OctoPrint.

Steps
  • From the OctoPrint web site, I download OctoPi 0.17.0. 
  • Using Etcher, burned the image to a 16GB SD card. 
  • Updated the file octopi-wpa-supplicant.txt with my network credentials. 
  • ssh to the pi
  • ran raspi-config
    • changed the user password
    • change timezone
    • rebooted the pi
  • Using a browser, I navigated to the IP of the OctoPi and followed the prompts to set up the first user
At this point, I paused to explore the interface. While I was exploring, OctoPrint went ahead with checking for updates. Updates were discovered and I went ahead with installing them.

Plugins
  • Bed Visualizer
    • Displays 3D mesh of bed topography report
    • Settings
      • General
        • GCODE Commands for Mesh Update Process
          • G28
          • G29 T
  • EEPROM Marlin Editor
  • Floating Navbar
  • Heater Timeout
    • Settings
      • Enable
  • Navbar Temperature
    • Display temperatures on navbar
  • Octolaspe
    • Creates a stabilized timelapse
  • Octoslack
    • monitoring your printer and prints via Slack, Mattermost, Pushbullet, Pushover, Rocket.Chat, Discord, Riot/Matrix, or Microsoft Teams
  • Simple Emergency Stop
  • Themeify


21 June, 2020

Restarting my 3D Printing hobby

Recently, I decided that I missed playing with, working with, and modifying my 3D printer. After a bit of research, I settled on purchasing the Ender 5 Plus.

While I was waiting for the printer to arrive I spent time watching YouTube videos on how to assembly the printer. I picked up several helpful tips and tricks. The Assembly of the printer was quick and easy. 

My first challenge came in leveling the bed. The blame for the challenge is all my fault. I didn't read the documentation carefully. I am made a bad assumption about how the software worked and what steps I needed to perform. Once I did read the documentation and watched a couple of videos, it took about 20 minutes to level the bed. I went through the AUX leveling steps twice just to make sure the bed as fairly level. For leveling, I had the build plate heated to 70 C and the hot-end to 190 C. The Auto-leveling sequence was run.

For the slicing program, I am using Cura 4.6.1. For my first print, the calibration cube was used. I took the defaults that Cura has for the Ender 5 Plus and send the gcode to the SD card. 

Here is where my second challenge appeared. When I put the card into the SD slot the printer didn't find the file. Turns out that the gcode needs to placed at the root level on the SD card and the file name can't be longer than 15 characters. 

Once the file was renamed, the printer recognized the existence of the file. I was then able to get the print started. When the hot-end starting moving from the home position to the starting point of the priming line the extruder sent filament to the hot-end. The priming line printed without issue. The skirt and cube printed without issue. 

I noticed during the print that the heated build got turned off or set to 0. I didn't manually adjust the bed's temperature settings. I also noted a strange noise when the infill was being printed. 



Took several measurements on the X, Y, and Z faces. I got a reading of +/- of .05 mm for most of the cube. The exception was the first two layers which were - .2 mm in the X and Y direction. 

This seems like a reasonable first print. 



ToDo
  • Examine the gcode for purge/prime sequence, to determine if I can get rid of the line the prints from the home position to the start of the purge/prime line.
  • Examine the gcode for changes to the bed temperature to determine if the gcode is turning off the bed or if the firmware is turning off the bed. 

16 February, 2020

Rebuild my docker lab setup

Background

Over the last few weeks, I have rebuilt my Docker lab and Home Assistant set up a few times.  The heart of the setup is a Raspberry 4. Finally, all the hardware I ordered has arrived and I have a bit of time to rebuild my setup. Hopefully, I won't need to rebuild for a while.

Plan

This time I want to set up a Rasberry Pi 4 Model B (2GB) with Raspbain Buster then configure the Pi to use a 1 TB SSD. Since the Rasberry Pi 4 doesn't currently support booting from an SSD, I will use the workaround from James Chambers. Once the Rasberry Pi is set up and a basic configuration is done, I will then install IOTstack from Graham Garner. This will help me set up Docker, HASS.io, Portainer, Mosquitto, and Tasmoadmin.

What I am hoping to get out of this is a stable platform for learning and experimenting with Docker,  Home Automation, Internet of Things, and electronics.

Notes

Setting up the Raspberry Pi

  • Used balenaEtcher to flash Raspbian Buster with desktop to an 8 Gig SD Card
  • Used balenaEtcher to flash Raspbian Buster with desktop to a 1 TB SSD
  • Plugged in a monitor, keyboard, mouse, network cable and applied power
    • I waited for about 5 minutes for the system to run through its first-time power-up.
  • created an empty file named ssh and placed it the boot folder for both SD and SSD
    • created the file wpa_supplicant.conf and placed it in the boot folder for both SD and SSD
    • Set basic config values for keyboard
    • changed the pi default password
    • skipped the update
  • sudo fdisk /dev/sda
    • set the SSD PARTUUID to d34db33f
  • sudo blkid
  • made backup of /boot/cmdline.txt
  • edited /boot/cmdline.txt to use the PARTUUID that was set earlier
  • sudo reboot
  • verified the SSD is being used
    • findmnt -n -o SOURCE /
  • updated /etc/fstab 
    • changed the PARTUUID to d34db33f
  • sudo reboot
  • resizing filesystem
    • delete the partition /dev/sda2
    • create a new partition with a first sector at 532480
    • sudo resize2fs /dev/sda2
      • This takes a while
    • df -h 
      • verify /dev/root shows a size value close to the size of the drive
  • sudo reboot

Configuring the Raspberry Pi

  • set Hostname
  • boot to CLI
  • auto login: uncheck mark
  • sudo reboot
  • verified Raspberry Pi configuration
  • verified that I can ssh into the raspberry pi
  • sudo apt update
  • sudo apt upgrade

Install IOTstack

  • ensure git is installed
    • sudo apt install git
  • clone IOTstack
    • git clone https://github.com/gcgarner/IOTstack.git ~/IOTstack
  • run menu
    • cd IOTstack
    • ./menu.sh
      • installed docker
      • installed Hass.io
      • installed Portainer
      • installed Mosquitto
      • installed tasmoadmin
  • docker-compose up -d




References

Github gcgarner / IOTstack







26 January, 2020

Setting up Home Assistant on Raspberry Pi using generic Linux host method



Recently my installation of Home Assistant died. It appears that I burned up the SD card. I can no longer read the SD Card. When I run gparted against the SD card, the card mounts in read-only mode. After a bit of research, I came up with a plan.

Rough Plan


  • Install the latest Raspbian Buster image
  • Reconfigure the Pi to run from a hard drive
  • Install Home Assistant using the generic Linux host method

Steps

  • Downloaded Raspbian Buster with desktop from the Raspberry Pi website
  • Using balenaEtcher to flash Buster to an SD card (8GB)
  • Booted the Pi for the first time
  • Setup the language, keyboard, and timezone. 
    • Changed the pi user's password
    • Selected the WiFi network
    • Updated the software
  • Updated the packages
    • sudo apt update
    • sudo apt upgrade
    • sudo reboot
  • Followed the directions from the blog post 'Quick SD to SSD on the pi 4'
    • use the utility 'SD Card Copier' to copy the SD card to the hard drive
    • run 'sudo blkid' to get the UUID of the SD sard and the hard drive
    • backup the file /boot/cmdline.txt
    • edit the file /boot/cmdline.txt. Change the partuuid from using the SD card to the hard drive
    • reboot
    • Note: must leave the SD card in the Raspberry Pi
  • Changed the hostname of the Pi
  • Enabled SSH on the Pi
  • Setup ssh key on my main PC
    • ssh-keygen
    • ssh-copy -i ~/.ssh/key-name pi@ip.address
    • ssh-add
  • Disable Password Authentication on the Pi
    • sudo nano /etc/ssh/sshd_config
      • Uncommented the line 'PasswordAuthentication yes'
      • changed yes to no
  • Set a static IP for the Pi
    • edit /etc/dhcpcd.conf
      • added
        • interface wlan0
        • static ip_address=XXX.XXX.XXX.XXX
        • static routers=XXX.XXX.XXX.XXX
        • static domain_name_servers=XXX.XXX.XXX.XXX
    • reboot
  • Changed Pi Configuration to boot to cli
  • Followed the directions from the blog post 'Install Docker and Docker Compose on Raspberry pi 4(Raspbian Buster)'
    • curl -sSL get.docker.com | sh
    • sudo usermod -aG docker pi
    • sudo apt-get install libffi-dev libssl-dev
    • sudo apt install python3-dev
    • sudo apt-get install -y python3 python3-pip
    • sudo pip3 install docker-compose
  • Followed installer for a generic Linux system
    • sudo apt install bash
    • sudo apt install jq
    • sudo apt install curl
    • sudo apt install avahi-daemon
    • sudo apt install dbus
    • sudo apt install apparmor-utils
  • curl -sL https://raw.githubusercontent.com/home-assistant/hassio-installer/master/hassio_install.sh | bash -s -- -m raspberrypi4-64
  • Setup Home Assistant
There was an issue with Home Assistant connecting to the internet. I removed the changes to /etc/dhcpcd.config. This seems to have helped. 

23 December, 2019

Third stop on the Docker learning train - Quickstart: Compose and ASP.NET Core with SQL Server

The third stop on my Docker learning train is a recommendation from the Docker Samples. The tutorial is titled 'Quickstart: Compose and ASP.NET Core with SQL Server'. This is going to be a whistle-stop.

This tutorial shows using the Docker Engine running on Linux to set up and run an ASP.NET Core application using a .NET Cor SKD image and SQL Server on Linux image. The tutorial makes use of Docker Compose for defining and running multiple container applications.

The tutorial references an older version (2.1) of the .NET Core libraries. My computer is running a newer (3.1) version of the .NET Core libraries. I wanted to see what error messages and problems running this setup would be.

The first change I made was to the docker-compose.yml file. I changed the port from 8000 to 9090 because I already had a different container using port 8000 and 9000. The second change made was in the "startup.cs" file. I commented out the setting up the connection variable. I moved the value of the connection to the "DefaultConnection" in the "appsettings.json" file. I needed to make a few more changes to the rest of the "ConfigureServices" method.


public void ConfigureServices (IServiceCollection services) {
    // Database connection string.
    // Make sure to update the Password value below from "Your_password123" to your actual password.
    // var connection = @"Server=db;Database=master;User=sa;Password=Your_password123;";

    services.Configure (options => {
    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
        });

    services.AddDbContext (options =>
        options.UseSqlServer (
            Configuration.GetConnectionString ("DefaultConnection")));
    services.AddDefaultIdentity ()
        .AddEntityFrameworkStores ();

    services.AddMvc ().SetCompatibilityVersion (CompatibilityVersion.Version_2_1);
}

On my computer, I encountered an issue with running 'docker-compose build'. The error message was
"ERROR: Couldn't connect to Docker daemon at http+docker://localhost - is it running?
If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable."
After a bit of research, I came to find out that this is a fairly generic and common message that could have several possible causes. For me, it turned out the I needed to change the permissions on the "docker.sock" file. I fixed the issue be running
sudo chmod 666 /var/run/docker.sock

The running of the command 'docker-compose up' wrote many messages to the console that gives the appearance of that the application and database are running. I can also have a couple of active containers. When I navigate to localhost:9090, the browser displays a "This site can't be reached" message. I am not going to take the time to figure out the problem at this time.



References 

Docker Compose - "Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration."

The article on Medium "If you faced an issue like 'Couldn't connect to Docker daemon at http+docker://localunixsocket -- is it running?'..." was helpful in dealing with an error from running 'docker-compose build'





19 December, 2019

Second stop on the Docker learning train - Dockerize an ASP.NET Core application

The second stop on my Docker learning train is a recommendation from the Docker Samples. The tutorial is titled 'Dockerize an ASP.NET Core application'.

When I first read through the tutorial, I figured this was going to be quick and easy. Due to making a few mistakes in creating the Dockerfile, I ended up with a few lessons learned.

The first lesson I learned was to read the output from running the docker build command carefully. It was interesting to see that the Docker daemon creates and removes intermediate containers.

The next lesson was when a container reports an error code 145 carefully double-check the Dockerfile. Pay close attention to what is being used for the DotNet Core runtime. The 'SDK' should be used for the restore and publish command while 'ASPNET' should be used for the runtime.

Another lesson learned is to use '.dockerignore' file to keep from unnecessary files from being included in the image.

The last lesson was to use interactive mode. The tutorial did not go through the steps I needed to do a bit of research to figure it out. The Alpine image does not include bash. I modified the Dockerfile to pull in bash and a few other tools. Rebuilt the image. The used the interactive mode switches to get a command prompt.

Dockerfile:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine AS build
WORKDIR /app/aspnetapp

# copy csproj and restore as distinct layers
COPY myWebApp/*.csproj ./
RUN dotnet restore

# copy everything else and build app
COPY myWebApp/. ./
RUN dotnet publish -c Release -o out

# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine AS runtime
WORKDIR /app
COPY --from=build /app/aspnetapp/out .

# Uncomment the following line to install bash and other tools useful for debugging
RUN apk add --no-cache bash coreutils grep sed

ENTRYPOINT ["dotnet", "myWebApp.dll"]

Command to build the image.

docker build -t {image name} .

Command to start the container in interactive mode and to override the default entry point

docker run -it --entrypoint /bin/bash {image name}

Reference

.dockerignore file
"Before the docker CLI sends the context to the docker daemon, it looks for a file named .dockerignore in the root directory of the context. If this file exists, the CLI modifies the context to exclude files and directories that match patterns in it. This helps to avoid unnecessarily sending large or sensitive files and directories to the daemon and potentially adding them to images using ADD or COPY." - https://docs.docker.com/engine/reference/#dockerignore-file

14 December, 2019

First stop on the Docker learning train - Docker for beginners

The first stop on my Docker learning train is from the Docker Samples with the tutorial Docker for beginners.

The tutorial has four chapters:
  • Setup
  • 1.0 Running your first container
  • 2.0 Webapps with Docker
  • 3.0 Deploying an app to a Swarm

Setup

The Setup chapter makes sure that Docker is installed and running on my machine. The tutorial points back to the Docker documentation for the installation steps. To verify that Docker is working run the following:
docker run hello-world

1.0 Running your first container

The key topics for this chapter include:
  • How to run a docker container.
  • How to list containers.
  • How to inspect a container.

Docker CLI commands

  • docker pull - pulls an image or repository from a registry
  • docker run - runs a container
    • This command can also pull a container
    • By default, the interactive shell will exit after running a script. Use the '-it' switch to keep the shell open.
      • Example: 
        docker run -it alpine /bin/sh
        
  • docker ps - list containers
    • By default, the command lists the running containers. 
    • To list all the containers use the switch '-a'
      • Example:
        docker ps -a
  • docker inspect - returns low-level information about a docker container

Terms

image - Docker images are the basis of containers. An Image is an ordered collection of root filesystem changes and the corresponding execution parameters for use within a container runtime. An image typically contains a union of layered filesystems stacked on top of each other. An image does not have state and it never changes. - Docker Glossary
container - A container is a runtime instance of a docker image.
A Docker container consists of
  • A Docker image
  • An execution environment
  • A standard set of instructions
The concept is borrowed from Shipping Containers, which define a standard to ship goods globally. Docker defines a standard to ship software. - Docker Glossary

2.0 Webapps with Docker

This chapter is broken into a few sections.

2.1 Run a static website in a container

Key topics for the section include:
  • How to run a container in detached mode.
  • How to publish the ports the container exposes.
  • How to name a container.
  • How to pass environment variables to the container.
  • How to stop a container.
  • How to remove a container.

2.2 Docker Images

Key topics for this section include:
  • What is a Docker image?
  • How to use 'tag' to pull a specific version of a container.

2.3 Create your first image

Key topics for this section include:
  • How to write a Dockerfile.
  • How to build the image.
  • How to run the image.
Notes about Dockerfiles

  • By convention, an instruction is written in UPPERCASE. This makes it easier to distinguish an instruction from an argument. 
  • Docker runs instructions in order.
  • A Dockerfile must begin with a 'FROM' instruction. 
  • Lines the begin with '#' are treated as a comment.
  • Guide: Best practices for writing Dockerfiles

Terms

base image - A base image has no parent image specified in its Dockerfile. It is created using a Dockerfile with the FROM scratch directive.
Child images are images that build on base images and add additional functionality. 
Official images are Docker sanctioned images. 
User images are images created and shared by users like you.
Dockerfile is a text document that contain all the commands a user could call on the command line to assemble an image. 

Docker CLI commands

  • docker run
    • -d - detached mode
    • -P - publish exposed container ports to random ports on the host
    • -e - pass environment variables to the container.
    • --name - allows a name to be specified for the container
  • docker stop - stops one or more containers
  • docker rm - removes one or more containers
    • -f - Force removal of a running container
  • docker port - List port mapping or a specific mapping for a container
  • docker images - list images
  • docker pull 
    • by default, pull gets the latest version
    • to get a specific version include the tag 
      • Example: 
        docker pull ubuntu:12.04
        
  • docker search - search the Docker Hub for images
  • docker build - build an image from a Dockerfile
    • -t - Name and optional a tag in the 'name:tag' format
  • docker login - Log into a Docker registry
  • docker push - Push an image or a repository to a registry

3.0 Deploy an app to a Swarm

Key topics for this chapter include:

  • How to create a swarm.
  • How to deploy. 

I was unable to make the example work properly on my machine. The docker swarm and docker stack executed without reporting any errors. The command 'docker ps' reports multiple active containers. I will need to come back to this tutorial at a later date to investigate further.

Terms

swarm - A swarm is a cluster of one or more Docker Engines running in swarm mode
Docker Swarm - Do not confuse Docker Swarm with the swarm mode features in Docker Engine.
Docker Swarm is the name of a standalone native clustering tool for Docker. Docker Swarm pools together several Docker hosts and exposes them as a single virtual Docker host. It serves the standard Docker API, so any tool that already works with Docker can now transparently scale up to multiple hosts.
Also known as : docker-swarm
swarm mode - Swarm mode refers to cluster management and orchestration features embedded in Docker Engine. When you initialize a new swarm (cluster) or join nodes to a swarm, the Docker Engine runs in swarm mode.

Docker CLI Commands







07 December, 2019

Learning a bit about Docker


What is Docker?

Docker is a tool to develop, ship and run applications. The heart of Docker is the container. A Docker container contains all the parts needed to run an application.

Install

I am currently running Pop!_OS 19.10. Which made installing Docker a bit more interesting. Pop!_OS 19.10 is based on Ubuntu 19.10. The official Docker documentation shows support for Ubuntu 19.04. For the most part, I followed the official documentation to install. When it came time to add the source I used the following.

sudo add-apt-repository "deb https://download.docker.com/linux/ubuntu disco stable"

The rest of the instructions were easy to follow and didn't require any modifications.

I also run the 'Optional Linux post-installation steps'. These steps should allow me to run docker commands from a terminal without preface a command without the 'sudo' keyword. For some reason, this is not working for me. I have verified that the group exists and my user account is part of the group. Additional research is needed.

Reading

I spent a bit of time reading through the official Docker documentation. There is a lot of information to absorb. There is way too much information to summarize in a single blog post. I am going to need a break the information down into smaller chunks.

Plan

From the Docker Samples work the following tutorials:

From Play with Docker Classroom work the following tutorials:
From Docker Curriculum work the following tutorials:

Resources

02 September, 2019

Setting up Home Assistant

What is Home Assistant?

"Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server." - https://www.home-assistant.io

I like to think of Home Assistant as the central hub to connect and control devices around my home. Most of the home automation items (light bulb and light switches) are just fancy remote-controlled devices. The hub should give me a way to control devices from different vendors, a way to step automations (turn on lights when at certain times), and a little future-proofing. 

Why Home Assistant?

Basically three reasons, the first is I have a Raspberry Pi 3B+ not dedicated to anything yet. The second is the price of Home Assistant. Lastly, I want the ability to tinker with the software.

Setup


  • Downloaded install image 
    • Raspberry Pi 3 Mobel b and B+ 64bit
  • Used GParted to repartition an old 32GB SD card
  • Flashed the image to the SD card
  • Connected or inserted the Raspberry Pi to 
    • Monitor
    • Keyboard
    • Mouse
    • Network - hard wire for now
    • the newly flashed SD card
    • power
  • Wait
    • This can take a while
      • Allow 20 or so minutes 
      • An updated version of the software is being downloaded and installed
      • I got the message 'IPv6: ADDRCOF(NETDEV_UP): wlan0: link is not ready'. 
        • I cycled the power to the Pi.
        • Same message appeared
        • hit return a few times
        • got a login prompt
        • the default username is root

  • Add wireless
    • Using the info from 'Using nmcli to set a static IPV4 address'
    • Got to Hassio login prompt then ran the following commands
      • login
      • nmcli connection show
      • nmcli radio
      • nmcli device
      • nmcli device wifi rescan
      • nmcli device wifi list
      • nmcli device wifi connect {SSID Nane} password {password}
      • nmcli device 
      • nmcli con edit "{connection Name}"
        • print ipv4
        • set ipv4.addresses {IP of my choice}
        • set ipv4.dns {DNS address}
        • set ipv4.gateway {gateway address}
        • save
        • print ipv4
        • quit
      • nmcli con reload
    • rebooted the Pi
      • unplugged the hardwire
      • Tested wireless
        • navigated to {IP}:8123
  • First-time setup
    • After navigating to IP:8123
    • followed prompts on the screen

Resources

Home Assistant


balenaEtcher
GParted
nmcli

Challenging myself to learn something new

I have recently set a big challenge for myself. I want to know about Machine Learning . To add to the challenge, I am trying out usin...