Compare commits
64 Commits
56282d75af
...
main
Author | SHA1 | Date | |
---|---|---|---|
474050ff6d
|
|||
1b95f46544 | |||
a4b13fb71e
|
|||
d512ff1c73
|
|||
b7c38ddc89
|
|||
9d602fede7
|
|||
a21898048c
|
|||
5e3bdbe2f6
|
|||
1e90d6c8a9
|
|||
b6c9129fa5
|
|||
00b08276a2
|
|||
47bfb4ac20
|
|||
1055f83d3a
|
|||
a9cb29989d
|
|||
ce04f5dd57
|
|||
ef43740721
|
|||
b94dba3163
|
|||
816896537d
|
|||
ad7096bca2
|
|||
37618fe7eb
|
|||
8c16a0d537
|
|||
e203b294c5
|
|||
91e7c9701a
|
|||
9e12734c5f
|
|||
524465453a
|
|||
dec593c503
|
|||
56d55a6617
|
|||
15cec82789
|
|||
8185cd14e4
|
|||
e4a0ef25e1
|
|||
5f5e43e54e
|
|||
a24eb028a9
|
|||
996700bec9
|
|||
4369e246bd
|
|||
a42bfcc814
|
|||
3de79c2111
|
|||
da516f5160
|
|||
0489963eda
|
|||
8981e9b9c4
|
|||
dd35b48def
|
|||
0ceb20bcf1
|
|||
f266085c4e
|
|||
5b64235c97
|
|||
b3d42c30d9
|
|||
a84913e3f5
|
|||
557bad8387
|
|||
0f29002415
|
|||
11cd8df774
|
|||
a92f99dae8
|
|||
7f7955fc4f
|
|||
a4d8d95d74
|
|||
bec5809694
|
|||
4e51f23dca
|
|||
212cfd6e4c
|
|||
c58e7b2f94
|
|||
307c4f366d
|
|||
3b0d086ea0
|
|||
4b59dcaa8b
|
|||
55b75039bf
|
|||
cde7a3c7f9
|
|||
b0f8043db0
|
|||
6e748d46b2
|
|||
f2e94c592f
|
|||
f8785c4fd2
|
11
blog/first_post.md
Executable file
11
blog/first_post.md
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
author: Akbar Rahman
|
||||||
|
pub_date: Fri, 31 Jul 2020 19:52:52 +0100
|
||||||
|
title: first post
|
||||||
|
tags: []
|
||||||
|
uuid: fd338dc9-ae5f-48f4-9fc6-e02e88ab4ce5
|
||||||
|
---
|
||||||
|
|
||||||
|
# first post
|
||||||
|
|
||||||
|
this is my first post
|
182
blog/g27_pedals.md
Executable file
182
blog/g27_pedals.md
Executable file
@@ -0,0 +1,182 @@
|
|||||||
|
---
|
||||||
|
author: Akbar Rahman
|
||||||
|
pub_date: Tue, 04 Aug 2020 15:20:13 +0100
|
||||||
|
title: Repurposing Racing Wheel Pedals
|
||||||
|
tags: [ g27, sim_racing ]
|
||||||
|
uuid: 0f09200e-fd50-451b-aae1-1117a8a704db
|
||||||
|
---
|
||||||
|
|
||||||
|
<h1>Repurposing Racing Wheel Pedals</h1>
|
||||||
|
<p>I have a Logitech G27 I don't use much. I wondered if I could use it for anything else. I could. </p>
|
||||||
|
|
||||||
|
<h2> The Pinout of the Connector </h2>
|
||||||
|
|
||||||
|
<p>The first thing I had to do was figure out what each pin did on the DE-9 connector, and which
|
||||||
|
ones I should care about.
|
||||||
|
This was done easily after I took off the top plastic casing thing by poking the three 100k Ohm
|
||||||
|
potentiometers and the connector in the right places at the right times:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<style> #pinout_table tr td:first-child { text-align: right } </style>
|
||||||
|
<img src="./images/repurposing-racing-wheel-pedals-g27-pinout.svg" class="centered" style="width: 10em;">
|
||||||
|
<table id="pinout_table">
|
||||||
|
<tr> <th>pin</th> <th>function</th></tr>
|
||||||
|
<tr> <td>1,4</td> <td>ground</td></tr>
|
||||||
|
<tr> <td>6</td> <td>clutch pedal</td></tr>
|
||||||
|
<tr> <td>7</td> <td>brake pedal</td></tr>
|
||||||
|
<tr> <td>8</td> <td>accelerator pedal</td></tr>
|
||||||
|
<tr> <td>9</td> <td>voltage in</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2> Reading the Values of the Pots </h2>
|
||||||
|
|
||||||
|
I'm using an Arduino to read the pots and then do something with the values.
|
||||||
|
I very dirtily wired pin 4 on the pedals to GND on a Arduino Uno, pin 9 to 5V, and
|
||||||
|
pins 6,7,8 to A0, A1, and A2.
|
||||||
|
I used a basic sketch to check that everything is good:
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary> Show/hide test_sketch.ino </summary>
|
||||||
|
<pre><code> void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
Serial.println(analogRead(A2));
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
I noticed that the minimum and maximum values read by the Uno were quite far off 0 and 1024, like
|
||||||
|
they should be, and voltage was being lost on the way to and from the potentiometers.
|
||||||
|
Since the pedals have to be calibrated every time you plug them in, I assume this is normal and
|
||||||
|
spat out this code:
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary> Show/hide sketch_aug02a.ino </summary>
|
||||||
|
<pre><code>// sensor pins
|
||||||
|
int sa = A0;
|
||||||
|
int sb = A1;
|
||||||
|
int sc = A2;
|
||||||
|
|
||||||
|
// minimum values detected by the sensors
|
||||||
|
int mina = 1025;
|
||||||
|
int minb = 1025;
|
||||||
|
int minc = 1025;
|
||||||
|
|
||||||
|
// maximum values detected by the sensors
|
||||||
|
int maxa = 512;
|
||||||
|
int maxb = 512;
|
||||||
|
int maxc = 512;
|
||||||
|
|
||||||
|
// raw values of the sensors
|
||||||
|
int rva, rvb, rvc;
|
||||||
|
|
||||||
|
// calculated values of the sensors (between 0 and 1, this is the value sent to computer)
|
||||||
|
float cva, cvb, cvc;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
rva = analogRead(sa);
|
||||||
|
rvb = analogRead(sb);
|
||||||
|
rvc = analogRead(sc);
|
||||||
|
|
||||||
|
if (rva < mina) mina = rva;
|
||||||
|
if (rvb < minb) minb = rvb;
|
||||||
|
if (rvc < minc) minc = rvc;
|
||||||
|
|
||||||
|
if (rva > maxa) maxa = rva;
|
||||||
|
if (rvb > maxb) maxb = rvb;
|
||||||
|
if (rvc > maxc) maxc = rvc;
|
||||||
|
|
||||||
|
cva = (float)(rva-mina)/(float)(maxa-mina);
|
||||||
|
cvb = (float)(rvb-minb)/(float)(maxb-minb);
|
||||||
|
cvc = (float)(rvc-minc)/(float)(maxc-minc);
|
||||||
|
|
||||||
|
Serial.print('[');
|
||||||
|
Serial.print(cva); Serial.print(',');
|
||||||
|
Serial.print(cvb); Serial.print(',');
|
||||||
|
Serial.print(cvc);
|
||||||
|
Serial.print(']');
|
||||||
|
Serial.println();
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<h2> Actually Making the Numbers Do Something </h2>
|
||||||
|
|
||||||
|
This is where you can make the pedals do fun things.
|
||||||
|
I reworked another piece of code I wrote to do a similar thing to quickly create a script that
|
||||||
|
reads the values sent by the Arduino, and then simulate pressing a key combination.
|
||||||
|
The only thing I've done with this is set push-to-talk to ctrl-shift-alt-1.
|
||||||
|
I don't know what else I could use this for, maybe temporarily muting particular things, like music.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary> Show/hide pedalboard.py </summary>
|
||||||
|
<pre><code> #!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
import keyboard
|
||||||
|
import serial
|
||||||
|
|
||||||
|
class KeyState(Enum):
|
||||||
|
UP = 0
|
||||||
|
DOWN = 1
|
||||||
|
|
||||||
|
STATES = [KeyState.UP] * 3
|
||||||
|
THRESHOLD = 0.8
|
||||||
|
MACROS = ['ctrl+shift+alt+1', 'ctrl+shift+alt+2', 'ctrl+shift+alt+3']
|
||||||
|
|
||||||
|
def get_args():
|
||||||
|
""" Get command line arguments """
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('device')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
""" Entry point for script """
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
kb = serial.Serial(port=args.device, baudrate=9600)
|
||||||
|
while True:
|
||||||
|
handle(json.loads(kb.readline()))
|
||||||
|
except serial.serialutil.SerialException as e:
|
||||||
|
print(e)
|
||||||
|
print("Failed to connect to device... trying again")
|
||||||
|
time.sleep(1)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def handle(data):
|
||||||
|
global STATES
|
||||||
|
|
||||||
|
states = [KeyState.DOWN if value > THRESHOLD else KeyState.UP for value in data]
|
||||||
|
r = [handle_state_change(i, states[i]) if states[i] != STATES[i] else None for i in range(len(STATES))]
|
||||||
|
STATES = states
|
||||||
|
return r
|
||||||
|
|
||||||
|
def handle_state_change(key, newstate):
|
||||||
|
print(f"{key} {newstate}")
|
||||||
|
return keyboard.press(MACROS[key]) if newstate == KeyState.DOWN else keyboard.release(MACROS[key])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
sys.exit(main(get_args()))
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
sys.exit(0)
|
||||||
|
</code></pre>
|
||||||
|
</details>
|
226
blog/images/repurposing-racing-wheel-pedals-g27-pinout.svg
Normal file
226
blog/images/repurposing-racing-wheel-pedals-g27-pinout.svg
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
version="1.0"
|
||||||
|
width="68.148842"
|
||||||
|
height="34.400002"
|
||||||
|
viewBox="-138.624 -137.291 68.14884 34.400003"
|
||||||
|
id="Layer_1"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:docname="repurposing-racing-wheel-pedals-g27-pinout.svg"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><title
|
||||||
|
id="title1416">DE-9 Connector with numbers</title><metadata
|
||||||
|
id="metadata1308"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title>DE-9 Connector with numbers</dc:title><dc:date>2020-08-02</dc:date><dc:creator><cc:Agent><dc:title>alvierahman90</dc:title></cc:Agent></dc:creator><cc:license
|
||||||
|
rdf:resource="" /><dc:contributor><cc:Agent><dc:title>Original drawing from Mobius (maybe): https://commons.wikimedia.org/wiki/File:DSubminiatures.svg</dc:title></cc:Agent></dc:contributor></cc:Work></rdf:RDF></metadata><sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1722"
|
||||||
|
inkscape:window-height="1060"
|
||||||
|
id="namedview1306"
|
||||||
|
showgrid="false"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
inkscape:zoom="10.44492"
|
||||||
|
inkscape:cx="27.994898"
|
||||||
|
inkscape:cy="11.731109"
|
||||||
|
inkscape:window-x="1056"
|
||||||
|
inkscape:window-y="1094"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="Layer_1" /><defs
|
||||||
|
id="defs2584">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<g
|
||||||
|
id="g1336"
|
||||||
|
transform="rotate(180,-104.54958,-120.091)"
|
||||||
|
style="stroke:#454545;stroke-opacity:1"><g
|
||||||
|
transform="translate(-193.19312,-267.013)"
|
||||||
|
id="g2241"
|
||||||
|
style="stroke:#454545;stroke-opacity:1">
|
||||||
|
<circle
|
||||||
|
cx="66.588997"
|
||||||
|
cy="141.351"
|
||||||
|
r="2.2409999"
|
||||||
|
style="fill:none;stroke:#454545;stroke-opacity:1"
|
||||||
|
id="circle2243" />
|
||||||
|
<circle
|
||||||
|
cx="77.617996"
|
||||||
|
cy="141.351"
|
||||||
|
r="2.2409999"
|
||||||
|
style="fill:none;stroke:#454545;stroke-opacity:1"
|
||||||
|
id="circle2245" />
|
||||||
|
<circle
|
||||||
|
cx="88.643997"
|
||||||
|
cy="141.351"
|
||||||
|
r="2.2379999"
|
||||||
|
style="fill:none;stroke:#454545;stroke-opacity:1"
|
||||||
|
id="circle2247" />
|
||||||
|
<path
|
||||||
|
d="m 99.668,139.11 c 1.238,0 2.242,1.004 2.242,2.241 0,1.237 -1.004,2.24 -2.242,2.24 -1.233,0 -2.237,-1.003 -2.237,-2.24 0,-1.237 1.004,-2.241 2.237,-2.241 z"
|
||||||
|
style="fill:none;stroke:#454545;stroke-opacity:1"
|
||||||
|
id="path2249"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<circle
|
||||||
|
cx="110.697"
|
||||||
|
cy="141.351"
|
||||||
|
r="2.2409999"
|
||||||
|
style="fill:none;stroke:#454545;stroke-opacity:1"
|
||||||
|
id="circle2251" />
|
||||||
|
<circle
|
||||||
|
cx="72.102997"
|
||||||
|
cy="152.491"
|
||||||
|
r="2.2390001"
|
||||||
|
style="fill:none;stroke:#454545;stroke-opacity:1"
|
||||||
|
id="circle2253" />
|
||||||
|
<circle
|
||||||
|
cx="83.130997"
|
||||||
|
cy="152.491"
|
||||||
|
r="2.2390001"
|
||||||
|
style="fill:none;stroke:#454545;stroke-opacity:1"
|
||||||
|
id="circle2255" />
|
||||||
|
<path
|
||||||
|
d="m 94.156,150.252 c 1.237,0 2.238,1.003 2.238,2.237 0,1.237 -1.001,2.241 -2.238,2.241 -1.238,0 -2.242,-1.004 -2.242,-2.241 0,-1.234 1.004,-2.237 2.242,-2.237 z"
|
||||||
|
style="fill:none;stroke:#454545;stroke-opacity:1"
|
||||||
|
id="path2257"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<circle
|
||||||
|
cx="105.185"
|
||||||
|
cy="152.491"
|
||||||
|
r="2.2390001"
|
||||||
|
style="fill:none;stroke:#454545;stroke-opacity:1"
|
||||||
|
id="circle2259" />
|
||||||
|
</g><path
|
||||||
|
d="m -129.54912,-136.791 c -5.609,0 -9.4,4.518 -8.425,10.042 l 2.354,13.309 c 0.976,5.525 6.366,10.049 11.975,10.049 h 38.191005 c 5.608,0 10.996,-4.523 11.975,-10.049 l 2.354,-13.309 c 0.975,-5.524 -2.813,-10.042 -8.425,-10.042 z"
|
||||||
|
style="fill:none;stroke:#454545;stroke-opacity:1"
|
||||||
|
id="path2261"
|
||||||
|
inkscape:connector-curvature="0" /></g>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
|
||||||
|
x="-123.37334"
|
||||||
|
y="-129.7538"
|
||||||
|
id="text1340"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1338"
|
||||||
|
x="-123.37334"
|
||||||
|
y="-129.7538"
|
||||||
|
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">1</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
|
||||||
|
x="-112.29854"
|
||||||
|
y="-129.7538"
|
||||||
|
id="text1340-3"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1338-7"
|
||||||
|
x="-112.29854"
|
||||||
|
y="-129.7538"
|
||||||
|
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">2</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
|
||||||
|
x="-101.2884"
|
||||||
|
y="-129.7538"
|
||||||
|
id="text1340-9"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1338-8"
|
||||||
|
x="-101.2884"
|
||||||
|
y="-129.7538"
|
||||||
|
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">3</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
|
||||||
|
x="-90.565475"
|
||||||
|
y="-129.7538"
|
||||||
|
id="text1340-6"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1338-70"
|
||||||
|
x="-90.565475"
|
||||||
|
y="-129.7538"
|
||||||
|
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">4</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
|
||||||
|
x="-129.24457"
|
||||||
|
y="-105.27687"
|
||||||
|
id="text1340-4"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1338-84"
|
||||||
|
x="-129.24457"
|
||||||
|
y="-105.27687"
|
||||||
|
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">5</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
|
||||||
|
x="-117.9472"
|
||||||
|
y="-105.27687"
|
||||||
|
id="text1340-8"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1338-1"
|
||||||
|
x="-117.9472"
|
||||||
|
y="-105.27687"
|
||||||
|
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">6</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
|
||||||
|
x="-106.88921"
|
||||||
|
y="-105.27687"
|
||||||
|
id="text1340-68"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1338-5"
|
||||||
|
x="-106.88921"
|
||||||
|
y="-105.27687"
|
||||||
|
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">7</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
|
||||||
|
x="-94.538704"
|
||||||
|
y="-105.27687"
|
||||||
|
id="text1340-2"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1338-19"
|
||||||
|
x="-94.538704"
|
||||||
|
y="-105.27687"
|
||||||
|
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">8</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
|
||||||
|
x="-83.91153"
|
||||||
|
y="-105.27687"
|
||||||
|
id="text1340-96"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1338-0"
|
||||||
|
x="-83.91153"
|
||||||
|
y="-105.27687"
|
||||||
|
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">9</tspan></text>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 8.6 KiB |
63
blog/lastfm_bookmarklets.md
Executable file
63
blog/lastfm_bookmarklets.md
Executable file
@@ -0,0 +1,63 @@
|
|||||||
|
---
|
||||||
|
author: Akbar Rahman
|
||||||
|
pub_date: Mon, 18 Sep 2023 16:25:48 +0100
|
||||||
|
title: last.fm bookmarklets
|
||||||
|
tags: [ last.fm, scripts ]
|
||||||
|
uuid: e54ebf58-4033-4dae-81db-91db344f1311
|
||||||
|
---
|
||||||
|
|
||||||
|
# last.fm bookmarklets
|
||||||
|
|
||||||
|
last.fm doesn't let you see how many scrobbled you've made in one day particularly easily.
|
||||||
|
Here is a bookmarklet to solve that.
|
||||||
|
|
||||||
|
<label for="days"> Number of days to view: </label>
|
||||||
|
<input type="number" value="1" id="days" placeholder="Days"/><br><br>
|
||||||
|
<label for="offset"> Offset (e.g. 0 to include today, 7 to look at last week): </label>
|
||||||
|
<input type="number" value="0" id="offset" placeholder="Offset (Days)" /><br><br>
|
||||||
|
<label for="username"> last.fm username </label>
|
||||||
|
<input type="text" value="" id="username" placeholder="Username" /><br><br>
|
||||||
|
<input type="button" id="button" value="Generate bookmarklet"><br>
|
||||||
|
|
||||||
|
<p><a style="display: none" href="" id="scriptLink">Bookmark this link</a></p>
|
||||||
|
|
||||||
|
When you press generate bookmarklet, the values `OFFSET`, `DAYS`, `USERNAME` will be
|
||||||
|
subsituted and put into the link above.
|
||||||
|
It's always best to inspect bookmarklets though.
|
||||||
|
Inspect the page to view the script used to generate the bookmarklet.
|
||||||
|
|
||||||
|
<textarea cols="109" rows="15" readonly id="scriptText">
|
||||||
|
javascript: (() => {
|
||||||
|
const MILLESECONDS_PER_DAY = 1000 * 24 * 60 * 60;
|
||||||
|
const OFFSET;
|
||||||
|
const DAYS;
|
||||||
|
const USERNAME;
|
||||||
|
|
||||||
|
const currentDate = new Date();
|
||||||
|
const to = new Date(currentDate - (OFFSET * MILLESECONDS_PER_DAY));
|
||||||
|
const from = new Date(to - ((DAYS-1) * MILLESECONDS_PER_DAY));
|
||||||
|
const toDate = to.getFullYear() + "-" + (to.getMonth()+1) + "-" + to.getDate();
|
||||||
|
const fromDate = from.getFullYear() + "-" + (from.getMonth()+1) + "-" + from.getDate();
|
||||||
|
|
||||||
|
document.location = "https://www.last.fm/user/" + USERNAME + "/library?from=" + fromDate + "&to=" + toDate;
|
||||||
|
})();
|
||||||
|
</textarea>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.getElementById("button").addEventListener("click", () => {
|
||||||
|
scriptText = document.getElementById("scriptText").value;
|
||||||
|
offset = document.getElementById("offset").value;
|
||||||
|
days = document.getElementById("days").value;
|
||||||
|
username = document.getElementById("username").value;
|
||||||
|
|
||||||
|
newscript = scriptText.replace(
|
||||||
|
"OFFSET", "OFFSET = " + offset
|
||||||
|
).replace(
|
||||||
|
"DAYS", "DAYS = " + days
|
||||||
|
).replace(
|
||||||
|
"USERNAME", "USERNAME = '" + username + "'"
|
||||||
|
);
|
||||||
|
document.getElementById("scriptLink").href = newscript;
|
||||||
|
document.getElementById("scriptLink").style = "";
|
||||||
|
});
|
||||||
|
</script>
|
13
blog/readme.md
Normal file
13
blog/readme.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
title: alv's blog
|
||||||
|
author: Akbar Rahman
|
||||||
|
pub_date: Fri, 31 Jul 2020 19:50:51 +0100
|
||||||
|
blog: true
|
||||||
|
tags: [ alvs_blog, blog ]
|
||||||
|
uuid: 2d03893a-eb9b-4923-8024-a223ecbe72f7
|
||||||
|
---
|
||||||
|
|
||||||
|
# alv's blog
|
||||||
|
|
||||||
|
this is my blog.
|
||||||
|
i promise i will try to keep things posted here interesting.
|
57
computery_stuff/cadence_license_manager_null_parameter.md
Executable file
57
computery_stuff/cadence_license_manager_null_parameter.md
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
---
|
||||||
|
author: Akbar Rahman
|
||||||
|
date: \today
|
||||||
|
title: "Cadence License Manager Install - `java.lang.IllegalArgumentException: :locationICompSelected: Null parameter - InstallComponent ID`"
|
||||||
|
tags: [ cadence, license_manager, flexlm, java, errors ]
|
||||||
|
uuid: a5f46736-1ab8-4da1-8737-95de51c95d50
|
||||||
|
---
|
||||||
|
|
||||||
|
# Error
|
||||||
|
|
||||||
|
```
|
||||||
|
[root@host Downloads]# iscape/bin/iscape.sh -batch majorAction=InstallFromArchive archiveDirectory=$(realpath LCU04.30.000_lnx86.Base) installDirectory=$(realpath target)
|
||||||
|
Initializing InstallScape using JVM at /home/alvi/Downloads/iscape.04.23-s012/runtime/LNX86/bin/java. This might take some time...
|
||||||
|
|
||||||
|
WARNING: The DISPLAY environment variable has not been set.
|
||||||
|
InstallScape might not initialize.
|
||||||
|
|
||||||
|
|
||||||
|
InstallScape Installer (Batch Mode) - 04.23.s12
|
||||||
|
|
||||||
|
:locationICompSelected: Null parameter - InstallComponent ID
|
||||||
|
java.lang.IllegalArgumentException: :locationICompSelected: Null parameter - InstallComponent ID
|
||||||
|
at com.khanpur.installerng.ArchiveLocationManager.locationICompSelected(ArchiveLocationManager.java:143)
|
||||||
|
at com.khanpur.installerng.Installer.archiveLocationICompSelected(Installer.java:1156)
|
||||||
|
at com.khanpur.installer.gui.batch.BatchInstallfromarchive.execute(BatchInstallfromarchive.java:86)
|
||||||
|
at com.khanpur.installer.gui.batch.BatchView.initialize(BatchView.java:329)
|
||||||
|
at com.khanpur.installer.gui.batch.BatchView.<init>(BatchView.java:90)
|
||||||
|
at com.khanpur.installer.gui.InstallerUINoSplash.showBatch(InstallerUINoSplash.java:325)
|
||||||
|
at com.khanpur.installer.gui.BatchCommand.execute(BatchCommand.java:78)
|
||||||
|
at com.khanpur.util.TransactionCommand.execute(TransactionCommand.java:74)
|
||||||
|
at com.khanpur.util.Commandline.runCommands(Commandline.java:223)
|
||||||
|
at com.khanpur.installer.gui.InstallerUINoSplash.processCommandLine(InstallerUINoSplash.java:340)
|
||||||
|
at com.khanpur.installer.gui.InstallerUINoSplash.main(InstallerUINoSplash.java:372)
|
||||||
|
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
||||||
|
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
|
||||||
|
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
|
||||||
|
at java.lang.reflect.Method.invoke(Unknown Source)
|
||||||
|
at com.khanpur.installer.gui.InstallerUI.main(InstallerUI.java:123)
|
||||||
|
Failed with InstallScape JVM.
|
||||||
|
Now loading System JVM...
|
||||||
|
iscape/bin/iscape.sh: line 222: java: command not found
|
||||||
|
Error:
|
||||||
|
/usr/bin/which: no java in (/usr/local/bin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin)
|
||||||
|
Could not use JVM packaged with Installcape. The Java in your path did not work or could not find Java in your path. Ensure that Java 1.6 or later is in your PATH environment variable and restart InstallScape.
|
||||||
|
```
|
||||||
|
|
||||||
|
# Cause
|
||||||
|
|
||||||
|
Using the wrong filepath.
|
||||||
|
The Cadence archives have subfolders to split the software between multiple CDs (a relic of the
|
||||||
|
past perhaps).
|
||||||
|
The actual folder to use is the CDs.
|
||||||
|
|
||||||
|
# Solution
|
||||||
|
|
||||||
|
Use the folder that contains the `.sdx` files (in my case, add `/CDROM1` onto end of
|
||||||
|
`archiveDirectory`).
|
81
computery_stuff/cloudwatch_event_rule_lambda_ansible.md
Executable file
81
computery_stuff/cloudwatch_event_rule_lambda_ansible.md
Executable file
@@ -0,0 +1,81 @@
|
|||||||
|
---
|
||||||
|
author: Akbar Rahman
|
||||||
|
date: \today
|
||||||
|
title: Eventbridge Rule (Cloudwatch Rule) Does Not Invoke Lambda When Configured Through Ansible
|
||||||
|
tags:
|
||||||
|
- ansible
|
||||||
|
- aws
|
||||||
|
- aws_eventbridge
|
||||||
|
- aws_lambda
|
||||||
|
- cloudwatch
|
||||||
|
- eventbridge
|
||||||
|
- lambda
|
||||||
|
- permissions
|
||||||
|
uuid: df3ca083-b6ae-4e35-bb1c-8b3978117c57
|
||||||
|
---
|
||||||
|
|
||||||
|
# Eventbridge Rule (formerly Cloudwatch Rule) Does Not Invoke Lambda When Configured Through Ansible
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
After creating an Eventbridge rule to run a Lambda function with the Ansible module
|
||||||
|
[`amazon.aws.cloudwatchevent_rule`](https://docs.ansible.com/ansible/latest/collections/amazon/aws/cloudwatchevent_rule_module.html),
|
||||||
|
the rule does not run Lambda function when it should:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: "Create lambda function"
|
||||||
|
register: create_lambda
|
||||||
|
amazon.aws.lambda:
|
||||||
|
region: "{{ aws_ec2_region }}"
|
||||||
|
description: "My Lambda function"
|
||||||
|
name: "{{ lambda_name }}"
|
||||||
|
role: "{{ iam_role.iam_role.arn }}"
|
||||||
|
state: "present"
|
||||||
|
timeout: 120
|
||||||
|
vpc_security_group_ids: "{{ sec_group.group_id }}"
|
||||||
|
vpc_subnet_ids: "{{ subnet_ids }}"
|
||||||
|
image_uri: "{{ ecr.repository.repositoryUri }}:latest"
|
||||||
|
- name: "Schedule my Lambda function"
|
||||||
|
register: lambda_schedule_rule
|
||||||
|
amazon.aws.cloudwatchevent_rule:
|
||||||
|
name: "a_unique_rule_name"
|
||||||
|
region: "{{ aws_ec2_region }}"
|
||||||
|
schedule_expression: "rate(1 minute)"
|
||||||
|
state: "present"
|
||||||
|
targets:
|
||||||
|
- arn: "{{ create_lambda.configuration.function_arn }}"
|
||||||
|
id: "a_unique_id"
|
||||||
|
input: "{{ eventbridge_rule_lambda_event_input }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
Even though creating a seemingly identical setup through the AWS console works fine.
|
||||||
|
|
||||||
|
## Cause
|
||||||
|
|
||||||
|
The Eventbridge rule is not allowed to invoke this Lambda, as it is not in the Lambda's policy.
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
Use the
|
||||||
|
[`amazon.aws.lambda_policy`](https://docs.ansible.com/ansible/latest/collections/amazon/aws/lambda_policy_module.html)
|
||||||
|
module to allow the Eventbridge rule to invoke the Lambda.
|
||||||
|
Note that, if specifying the Lambda function name to `function_name` (as opposed to the ARN of the
|
||||||
|
Lambda function), you must specify `version` or otherwise the Lambda function still won't be run!
|
||||||
|
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: "Allow Eventbridge (Cloudwatch) Rules to invoke lambda"
|
||||||
|
amazon.aws.lambda_policy:
|
||||||
|
action: "lambda:InvokeFunction"
|
||||||
|
function_name: "{{ lambda_name }}"
|
||||||
|
state: "present"
|
||||||
|
statement_id: "a_unique_statement_id"
|
||||||
|
region: "{{ aws_ec2_region }}"
|
||||||
|
principal: "events.amazonaws.com"
|
||||||
|
source_arn: "{{ lambda_schedule_rule.rule.arn }}"
|
||||||
|
version: "{{ create_lambda.configuration.version }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Solution found thanks to @david-kretch's answer to the same question at
|
||||||
|
<https://stackoverflow.com/questions/45282939/cloudwatch-event-rule-creation-via-ansible-succeeds-but-not-invoked>.
|
12
computery_stuff/flask.md
Executable file
12
computery_stuff/flask.md
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
author: Akbar Rahman
|
||||||
|
date: \today
|
||||||
|
title: Flask
|
||||||
|
tags: [ python, flask, programming, docker ]
|
||||||
|
uuid: e513ed96-cb19-4d4c-9894-e337c54659e5
|
||||||
|
---
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
- [alv.cx-glass](https://git.alv.cx/alvierahman90/alv.cx-glass) --- a pretty minimal example, probably not very production ready but has example of how to use in Docker
|
||||||
|
- <https://flask.palletsprojects.com/> --- official documentation for Flask
|
17
computery_stuff/jetson_nano.md
Executable file
17
computery_stuff/jetson_nano.md
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
author: Akbar Rahman
|
||||||
|
date: \today
|
||||||
|
title: Jetson Nano
|
||||||
|
tags: [ nvidia, jetson, jetson_nano, droidcam ]
|
||||||
|
uuid: f312451a-2cd4-468a-9eef-ca9859c7cd1e
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
# installing Droidcam
|
||||||
|
|
||||||
|
figured out with help from <https://hizzely.hashnode.dev/instalasi-droidcam-cli-di-jetson-nano> :pray:
|
||||||
|
|
||||||
|
0. build and install libjpeg-turbo version 2.1.2 from github (cmake, make, make install)
|
||||||
|
0. build droidcam (2.1.3 confirmed working) from source (make) and install (./install-client) (may need to set `PKG_CONFIG_PATH` environment varible to whatever libjpeg turbo installed at (for me, `/opt/libjpeg-turbo/lib64/pkgconfig`))
|
||||||
|
0. install v4l2loopback-dkms with apt
|
||||||
|
0. run droidcam (you may need to set `LD_LIBRARY_PATH` environment variable to wherever libjpeg-turbo installed to (for me, `/opt/libjpeg-turbo/lib64`))
|
@@ -20,3 +20,47 @@ usermod -a -G group user
|
|||||||
```bash
|
```bash
|
||||||
usermod -g group user
|
usermod -g group user
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# help i think my device shut down after deleting the current kernel and before installing the second (no entries in systemd-boot/grub/<bootloader>)
|
||||||
|
|
||||||
|
0. boot into a live usb of current disto
|
||||||
|
1. mount the root partition to `/mnt` and the boot partition to the appropriate folder (check
|
||||||
|
fstab which should be in `/mnt/etc/fstab`, if it says `/efi`, mount it to `/mnt/efi`)
|
||||||
|
2. chroot into the mounted filesystem:
|
||||||
|
|
||||||
|
on arch based systems you can simply run:
|
||||||
|
|
||||||
|
```
|
||||||
|
arch-chroot /mnt
|
||||||
|
```
|
||||||
|
|
||||||
|
on non arch based systems[^1]:
|
||||||
|
|
||||||
|
```
|
||||||
|
mount -t proc /proc /mnt/proc/
|
||||||
|
mount -t sysfs /sys /mnt/ys/
|
||||||
|
mount --rbind /dev /mnt/dev/
|
||||||
|
# only if using uefi
|
||||||
|
mount --rbind /sys/firmware/efi/efivars /mnt/sys/firmware/efi/efivars/
|
||||||
|
# for internet access
|
||||||
|
cp /etc/resolv.conf /mnt/etc/resolv.conf
|
||||||
|
chroot /mnt /bin/bash
|
||||||
|
```
|
||||||
|
3. the system can now be force updated/kernel images can be generated
|
||||||
|
|
||||||
|
on arch based systems[^2]:
|
||||||
|
|
||||||
|
```
|
||||||
|
# reinstall all current packages
|
||||||
|
pacman -Qqen > /root/pkgs.txt # list all installed packages
|
||||||
|
pacman -S $(< /root/pkgs.txt) # reinstall all installed packages
|
||||||
|
rm /root/pkgs.txt # clean up
|
||||||
|
|
||||||
|
# reinstall dependencies (if there are issues)
|
||||||
|
pacman -Qqdn > /root/deps.txt # list all installed dependencies
|
||||||
|
pacman -S $(< /root/deps.txt) # reinstall all installed dependencies
|
||||||
|
rm /root/deps.txt # clean up
|
||||||
|
```
|
||||||
|
|
||||||
|
[^1]: https://wiki.archlinux.org/title/Chroot [wayback machine](https://web.archive.org/web/20240121115548/https://wiki.archlinux.org/title/Chroot)
|
||||||
|
[^2]: https://bbs.archlinux.org/viewtopic.php?id=193174 [wayback machine](https://web.archive.org/web/20240129153400/https://bbs.archlinux.org/viewtopic.php?id=193174)
|
||||||
|
14
computery_stuff/uo_nottingham.md
Executable file
14
computery_stuff/uo_nottingham.md
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
author: Akbar Rahman
|
||||||
|
date: \today
|
||||||
|
title: University of Nottingham
|
||||||
|
tags: [ uni ]
|
||||||
|
uuid: d1b03938-c5b4-48ad-a258-78f96880aa4b
|
||||||
|
---
|
||||||
|
|
||||||
|
### Trying to log into Microsoft 365 sends me to a different organisation's login page
|
||||||
|
|
||||||
|
Try one of these links:
|
||||||
|
|
||||||
|
- <https://pls.cx/uon_email> (a redirect to the link below)
|
||||||
|
- <https://outlook.office.com/owa/nottingham.ac.uk>
|
@@ -6,4 +6,6 @@ cd `dirname $0`
|
|||||||
git pull
|
git pull
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf notes.alv.cx/*
|
rm -rf notes.alv.cx/*
|
||||||
notes2web.py -o notes.alv.cx notes
|
cd /root/gronk
|
||||||
|
git pull
|
||||||
|
docker compose up --build
|
||||||
|
10
readme.md
Normal file
10
readme.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: alv's notes
|
||||||
|
base_url: https://notes.alv.cx
|
||||||
|
---
|
||||||
|
|
||||||
|
# alv's notes
|
||||||
|
|
||||||
|
These are my personal notes. Correctness is not guaranteed.
|
||||||
|
|
||||||
|
Best viewed at [notes.alv.cx](https://notes.alv.cx).
|
12
styles.css
Normal file
12
styles.css
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
@import url("https://styles.alv.cx/fonts/comic-mono-font.css");
|
||||||
|
@import url("https://styles.alv.cx/modules/dotgrid.css");
|
||||||
|
@import url("https://styles.alv.cx/modules/alwaysdark.css");
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--dotgrid-size: 15em;
|
||||||
|
--dotgrid-dot-size: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Comic Mono', monospace;
|
||||||
|
}
|
@@ -226,10 +226,10 @@ design.
|
|||||||
Simply multiply the maximum stresses and loads you expect by the safety factor, $n_s$, and assume
|
Simply multiply the maximum stresses and loads you expect by the safety factor, $n_s$, and assume
|
||||||
that as your maximum stress and load.
|
that as your maximum stress and load.
|
||||||
|
|
||||||
$n_s$ | Operational conditions and use of materials
|
| $n_s$ | Operational conditions and use of materials |
|
||||||
----- | -------------------------------------------
|
|-----------|---------------------------------------------------------------------------------------------------------------------|
|
||||||
1.25-1.50 | Reliable materials under controlled conditions, known stresses with certainty
|
| 1.25-1.50 | Reliable materials under controlled conditions, known stresses with certainty |
|
||||||
1.50-2.00 | Well-known materials under reasonably constant environmental condition, known stresses
|
| 1.50-2.00 | Well-known materials under reasonably constant environmental condition, known stresses |
|
||||||
2.00-2.50 | Average materials subjected to known loads and stresses and environment (LSE)
|
| 2.00-2.50 | Average materials subjected to known loads and stresses and environment (LSE) |
|
||||||
2.50-3.00 | Lesser well-known materials under average conditions LSE
|
| 2.50-3.00 | Lesser well-known materials under average conditions LSE |
|
||||||
3.00-3.40 | Untried materials under average conditions of stresses and environment, or well known materials under uncertain LSE
|
| 3.00-3.40 | Untried materials under average conditions of stresses and environment, or well known materials under uncertain LSE |
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
uni/mmme/3049_engineering_management_2/images/xed_question.png
Normal file
BIN
uni/mmme/3049_engineering_management_2/images/xed_question.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 153 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
11
uni/mmme/3049_engineering_management_2/readme.md
Executable file
11
uni/mmme/3049_engineering_management_2/readme.md
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
author: Akbar Rahman
|
||||||
|
title: MMME3039 Engineering Management 2
|
||||||
|
tags: [ mmme3049, engineering_management, business ]
|
||||||
|
uuid: bca772c8-ea08-42fe-9fd0-8d9728cd6e8e
|
||||||
|
---
|
||||||
|
|
||||||
|
# MMME3039 Engineering Management 2
|
||||||
|
|
||||||
|
- [Anki Revision Flashcard](./MMME3049 Engineering Management.apkg)
|
||||||
|
- [Slides](./lecture_slides)
|
39
uni/mmme/3049_engineering_management_2/xed.md
Executable file
39
uni/mmme/3049_engineering_management_2/xed.md
Executable file
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
author: Akbar Rahman
|
||||||
|
date: \today
|
||||||
|
title: Cross Elastic Demand (XED)
|
||||||
|
tags: []
|
||||||
|
uuid: d6b6e3dd-1bba-466a-aad8-9e39c68280ab
|
||||||
|
---
|
||||||
|
|
||||||
|
# Cross Elastic Demand (XED)
|
||||||
|
|
||||||
|
The equation given in the lecture slides is:
|
||||||
|
|
||||||
|
$$\text{XED} = \frac{\frac{\Delta q_A}{q_A}}{\frac{\Delta p_B}{p_B}}$$
|
||||||
|
|
||||||
|
But that's a bit ambiguous, so it's better write as:
|
||||||
|
|
||||||
|
$$\text{XED}
|
||||||
|
= \frac{\frac{q_{A,2}-q_{A,1}}{q_{A,1}}}{\frac{p_{B,2}-p_{B,1}}{p_{B,1}}}
|
||||||
|
= \frac{\text{percentage change in quantity of A}}{\text{percentage change in price of B}}
|
||||||
|
$$
|
||||||
|
|
||||||
|
If XED is positive, the two goods A and B are substitutes for each other.
|
||||||
|
If XED is negative, the two goods are complimentary.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Here, product A is the CNC machining system and product B is the control software.
|
||||||
|
|
||||||
|
Quantity of product A sold can be found using $revenue = price \times quantity$:
|
||||||
|
|
||||||
|
$$quantity_1 = \frac{2\,250\,000}{11\,000} = 205$$
|
||||||
|
$$quantity_2 = \frac{4\,850\,000}{11\,000} = 441$$
|
||||||
|
|
||||||
|
$$\text{percentage change in quantity of A} = \frac{441-205}{205} = 1.156$$
|
||||||
|
$$\text{percentage change in price of B} = \frac{2600-6800}{6800} = -0.618$$
|
||||||
|
|
||||||
|
$$\text{XED} = \frac{1.156}{-0.618} = -1.871$$
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
30
uni/mmme/3081_thermodynamics_and_fluid_dynamics/readme.md
Executable file
30
uni/mmme/3081_thermodynamics_and_fluid_dynamics/readme.md
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
author: Akbar Rahman
|
||||||
|
date: \today
|
||||||
|
title: MMME3081 Thermofluids 3
|
||||||
|
tags: [ mmme3081, thermodynamics, fluid_dynamics, thermofluids ]
|
||||||
|
uuid: 8c0c0707-2148-4c5f-b3b7-0318f245a774
|
||||||
|
---
|
||||||
|
|
||||||
|
# MMME3081 Thermofluids 3
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
|
||||||
|
## Errata
|
||||||
|
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
### Turbomachinery, notes p. 2 (p. 16)
|
||||||
|
|
||||||
|
The equation for swirl angle, $\alpha$, may be wrong but Don wasn't sure
|
||||||
|
which one was the correct one in the lecture lol.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Formula Sheet
|
||||||
|
|
||||||
|
This module ideally will not have a dedicated formula sheet, instead giving the needed
|
||||||
|
equations in the paper, so use the
|
||||||
|
[MMME2047 formula sheet](../2047_thermodynamics_and_fluid_dynamics/data_and_formulae_sheets/formulae.pdf)
|
||||||
|
instead.
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# Akbar Rahman
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
x0, y0 = (5, 5)
|
||||||
|
x1, y1 = (18, 16)
|
||||||
|
|
||||||
|
dx = x1 - x0
|
||||||
|
dy = y1 - x0
|
||||||
|
D = 2 * dy - dx
|
||||||
|
y = y0
|
||||||
|
|
||||||
|
print(f"{dx=} {dy=} {D=} {y=}")
|
||||||
|
|
||||||
|
xs = []
|
||||||
|
ys = []
|
||||||
|
|
||||||
|
for x in range(x0, x1 + 1):
|
||||||
|
# moveto(x, y)
|
||||||
|
if D > 0:
|
||||||
|
y += 1
|
||||||
|
D -= 2 * dx
|
||||||
|
|
||||||
|
D += 2 * dy
|
||||||
|
print(f"{D=}\t{x=}\t{y=}")
|
||||||
|
xs.append(x)
|
||||||
|
ys.append(y)
|
||||||
|
|
||||||
|
print(f"{xs=}")
|
||||||
|
print(f"{ys=}")
|
||||||
|
plt.plot(xs, ys)
|
||||||
|
plt.show()
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
author: Akbar Rahman
|
||||||
|
title: Mechatronics Exercise Sheets
|
||||||
|
uuid: 4385c6ab-bc61-4510-a587-b6c6a2dd9e7c
|
||||||
|
---
|
||||||
|
|
||||||
|
# Mechatronics Exercise Sheets
|
||||||
|
|
||||||
|
## Errata
|
||||||
|
|
||||||
|
### Exercise Sheet 2, Question 3
|
||||||
|
|
||||||
|
> Confirmed by module convenor.
|
||||||
|
|
||||||
|
The answers say that the final line:
|
||||||
|
|
||||||
|
```c
|
||||||
|
bool pinStatus = PINC & 0x08;
|
||||||
|
```
|
||||||
|
|
||||||
|
will read from pin 30, but it will actually read from pin 33.
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,39 @@
|
|||||||
|
enum daysOfWeek {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY};
|
||||||
|
int i = 0; // Number of the week days
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
for (i = 0; i < 7; i++){
|
||||||
|
int day=daysOfWeek(i); //if it is Sunday, day will be 0, if Monday it will be 1 and so on
|
||||||
|
Serial.print("Today is ");
|
||||||
|
switch (day)
|
||||||
|
{
|
||||||
|
case SUNDAY:
|
||||||
|
Serial.print("SUNDAY: Go for Swiming");
|
||||||
|
break;
|
||||||
|
case MONDAY:
|
||||||
|
Serial.print("Monday: Go to Computer Engineering Lecture");
|
||||||
|
break;
|
||||||
|
case TUESDAY:
|
||||||
|
Serial.print("Tuesday: Go to Computer Engineering Laboratory");
|
||||||
|
break;
|
||||||
|
case WEDNESDAY:
|
||||||
|
Serial.print("Wednesday: Studay Mechatronics and Computer Engineering");
|
||||||
|
break;
|
||||||
|
case THURSDAY:
|
||||||
|
Serial.print("Thursday: Go to Mechatronics Lecture");
|
||||||
|
break;
|
||||||
|
case FRIDAY:
|
||||||
|
Serial.print("Friday: Go to Mechatronics Seminar");
|
||||||
|
break;
|
||||||
|
case SATURDAY:
|
||||||
|
Serial.print("Saturday: Take a rest");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Serial.print('\n');
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,300 @@
|
|||||||
|
/* Example of driving servomotor and reading encoder signals in various ways */
|
||||||
|
|
||||||
|
#include <avr/io.h> /* Needed to set up counter on pin 47 */
|
||||||
|
#include <SPI.h> /* Needed to communicate with LS7366R (Counter Click) */
|
||||||
|
|
||||||
|
/* Serial input aspects are based closely upon:
|
||||||
|
http://forum.arduino.cc/index.php?topic=396450
|
||||||
|
Example 4 - Receive a number as text and convert it to an int
|
||||||
|
Modified to read a float */
|
||||||
|
|
||||||
|
/* LS7366R aspects very loosely based on concepts used in controlling
|
||||||
|
the Robogaia 3-axis encoder shield though implementation is very different
|
||||||
|
https://www.robogaia.com/3-axis-encoder-conter-arduino-shield.html */
|
||||||
|
|
||||||
|
/* Counting using Timer 5 (external counter input) based loosely on code from
|
||||||
|
https://forum.arduino.cc/index.php?topic=59396.0 written by bubuldino */
|
||||||
|
|
||||||
|
/* Pins used for L298 driver */
|
||||||
|
#define enA 13 /* PWM output, also visible as LED */
|
||||||
|
#define in1 8 /* H bridge selection input 1 */
|
||||||
|
#define in2 9 /* H bridge selection input 2 */
|
||||||
|
#define minPercent -100.0
|
||||||
|
#define maxPercent 100.0
|
||||||
|
|
||||||
|
/* Encoder input pins (used for state machine and interrupts) */
|
||||||
|
#define channelA 2
|
||||||
|
#define channelB 3
|
||||||
|
|
||||||
|
/* Used to to initiate SPI communication to LS7366R chip (Counter click) */
|
||||||
|
#define chipSelectPin 10
|
||||||
|
|
||||||
|
/* Size of buffer used to store received characters */
|
||||||
|
#define numChars 32
|
||||||
|
|
||||||
|
/* Intervals in milliseconds for user-defined timed loops */
|
||||||
|
#define printInterval 1000
|
||||||
|
|
||||||
|
/* Global variables used in serial input */
|
||||||
|
char receivedChars[numChars]; // an array to store the received data
|
||||||
|
float dataNumber = 0; // new for this version
|
||||||
|
boolean newData = false;
|
||||||
|
|
||||||
|
/* Global variables used for motor control and encoder reading */
|
||||||
|
double percentSpeed;
|
||||||
|
double encoderValue;
|
||||||
|
|
||||||
|
/* Used for state machine and encoder reading */
|
||||||
|
typedef enum states{state1=1, state2, state3, state4};
|
||||||
|
volatile long int count = 0;
|
||||||
|
volatile long int error = 0;
|
||||||
|
volatile states state;
|
||||||
|
bool channelAState, channelBState;
|
||||||
|
|
||||||
|
/* Used for handling overflows in Timer 5 */
|
||||||
|
volatile long int bigLaps;
|
||||||
|
|
||||||
|
/* Global variables used for loop timing */
|
||||||
|
unsigned long prevMillisPrint = 0; /* stores last time values were printed */
|
||||||
|
unsigned long prevMillisControl = 0; /* stores last time control action was updated */
|
||||||
|
|
||||||
|
/* Overlapping regions of memory used to convert four bytes to a long integer */
|
||||||
|
union fourBytesToLong
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
unsigned char bytes [4];
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
Serial.println("Enter PWM duty cycle as a percentage (positive for forward, negative for reverse");
|
||||||
|
|
||||||
|
/* Set encoder pins as input but with pullup resistors to be compatible with various encoders */
|
||||||
|
pinMode(channelA, INPUT_PULLUP);
|
||||||
|
pinMode(channelB, INPUT_PULLUP);
|
||||||
|
|
||||||
|
channelAState = digitalRead(channelA);
|
||||||
|
channelBState = digitalRead(channelB);
|
||||||
|
|
||||||
|
initialiseEncoderStateMachine(); /* Find initial state based on inputs */
|
||||||
|
|
||||||
|
/* Set up and initialise pin used for selecting LS7366R counter: hi=inactive */
|
||||||
|
pinMode(chipSelectPin, OUTPUT);
|
||||||
|
digitalWrite(chipSelectPin, HIGH);
|
||||||
|
|
||||||
|
SetUpLS7366RCounter();
|
||||||
|
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
/* Configure Timer 5 to count pulses on pin 47 */
|
||||||
|
pinMode(47, INPUT_PULLUP); // set pin to input with pullup resistor
|
||||||
|
|
||||||
|
TCCR5A = 0; // No waveform generation needed.
|
||||||
|
TCCR5B = (1<<CS50) | (1<<CS51) | (1<<CS52); // Normal mode, clock from pin T5 on rising edge. T5 is Arduinos Pin 47
|
||||||
|
TCCR5C = 0; // No force output compare.
|
||||||
|
TCNT5 = 0; // Initialise counter register to zero.
|
||||||
|
TIMSK5= (1<<TOIE5); // Enable overflow interrupt
|
||||||
|
sei(); // Enable all interrupts
|
||||||
|
bigLaps = 0; // Initialise number of overflows
|
||||||
|
|
||||||
|
/* Configure control pins for L298 H bridge */
|
||||||
|
pinMode(enA, OUTPUT);
|
||||||
|
pinMode(in1, OUTPUT);
|
||||||
|
pinMode(in2, OUTPUT);
|
||||||
|
|
||||||
|
/* Set initial rotation direction */
|
||||||
|
digitalWrite(in1, LOW);
|
||||||
|
digitalWrite(in2, HIGH);
|
||||||
|
|
||||||
|
//attachInterrupt(digitalPinToInterrupt(channelA), updateEncoderStateMachine, CHANGE);
|
||||||
|
//attachInterrupt(digitalPinToInterrupt(channelB), updateEncoderStateMachine, CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
unsigned long currentMillis = millis();
|
||||||
|
|
||||||
|
if (currentMillis - prevMillisPrint >= printInterval) {
|
||||||
|
// save the last time you printed output
|
||||||
|
prevMillisPrint = currentMillis;
|
||||||
|
printLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
recvWithEndMarker();
|
||||||
|
if(convertNewNumber())
|
||||||
|
// Update value read from serial line
|
||||||
|
{
|
||||||
|
percentSpeed=dataNumber;
|
||||||
|
driveMotorPercent(percentSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateEncoderStateMachine();
|
||||||
|
}
|
||||||
|
|
||||||
|
void driveMotorPercent(double percentSpeed)
|
||||||
|
/* Output PWM and H bridge signals based on positive or negative duty cycle % */
|
||||||
|
{
|
||||||
|
percentSpeed = constrain(percentSpeed, -100, 100);
|
||||||
|
int regVal = map(percentSpeed, -100, 100, -255, 255);
|
||||||
|
analogWrite(enA, (int)abs(regVal));
|
||||||
|
digitalWrite(in1, regVal>0);
|
||||||
|
digitalWrite(in2, !(regVal>0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void printLoop()
|
||||||
|
/* Print count and control information */
|
||||||
|
{
|
||||||
|
/* Sample all counters one after the other to avoid delay-related offsets */
|
||||||
|
long encoderCountFromLS7366R = readEncoderCountFromLS7366R();
|
||||||
|
long encoderCountFromStateMC = count;
|
||||||
|
long stateMCerror = error;
|
||||||
|
long timer5Count = TCNT5 + bigLaps*65536;
|
||||||
|
Serial.print("Count from LS7366R = ");
|
||||||
|
Serial.print(encoderCountFromLS7366R);
|
||||||
|
Serial.print(" from state m/c = ");
|
||||||
|
Serial.print(encoderCountFromStateMC);
|
||||||
|
Serial.print(" State m/c errors = ");
|
||||||
|
Serial.print(stateMCerror);
|
||||||
|
Serial.print(" Count from LS7366R/4 = ");
|
||||||
|
Serial.print(encoderCountFromLS7366R/4);
|
||||||
|
Serial.print(" from Timer 5 = ");
|
||||||
|
Serial.print(timer5Count);
|
||||||
|
Serial.print(" Percent speed = ");
|
||||||
|
Serial.print(percentSpeed);
|
||||||
|
Serial.print("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
long readEncoderCountFromLS7366R()
|
||||||
|
/* Reads the LS7366R chip to obtain up/down count from encoder. Reads four
|
||||||
|
bytes separately then concverts them to a long integer using a union */
|
||||||
|
{
|
||||||
|
fourBytesToLong converter; /* Union of four bytes and a long integer */
|
||||||
|
|
||||||
|
digitalWrite(chipSelectPin,LOW); /* Make LS7366R active */
|
||||||
|
|
||||||
|
SPI.transfer(0x60); // Request count
|
||||||
|
converter.bytes[3] = SPI.transfer(0x00); /* Read highest order byte */
|
||||||
|
converter.bytes[2] = SPI.transfer(0x00);
|
||||||
|
converter.bytes[1] = SPI.transfer(0x00);
|
||||||
|
converter.bytes[0] = SPI.transfer(0x00); /* Read lowest order byte */
|
||||||
|
|
||||||
|
digitalWrite(chipSelectPin,HIGH); /* Make LS7366R inactive */
|
||||||
|
|
||||||
|
return converter.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SetUpLS7366RCounter(void)
|
||||||
|
/* Initialiseds LS7366R hardware counter on Counter Click board to read quadrature signals */
|
||||||
|
{
|
||||||
|
/* Control registers in LS7366R - see LS7366R datasheet for this and subsequent control words */
|
||||||
|
unsigned char IR = 0x00, MRD0=0x00;
|
||||||
|
|
||||||
|
// SPI initialization
|
||||||
|
SPI.begin();
|
||||||
|
//SPI.setClockDivider(SPI_CLOCK_DIV16); // SPI at 1Mhz (on 16Mhz clock)
|
||||||
|
delay(10);
|
||||||
|
|
||||||
|
/* Configure as free-running 4x quadrature counter */
|
||||||
|
digitalWrite(chipSelectPin,LOW); /* Select chip and initialise transfer */
|
||||||
|
/* Instruction register IR */
|
||||||
|
IR |= 0x80; /* Write to register (B7=1, B6=0) */
|
||||||
|
IR |= 0x08; /* Select register MDR0: B5=0, B4=0, B3=1 */
|
||||||
|
SPI.transfer(IR); /* Write to instruction register */
|
||||||
|
/* Mode register 0 */
|
||||||
|
MRD0 |= 0x03; /* 4x quadrature count: B0=1, B1=1 */
|
||||||
|
/* B2=B3=0: free running. B4=B5=0: disable index. */
|
||||||
|
/* B6=0: asynchronous index. B7: Filter division factor = 1. */
|
||||||
|
SPI.transfer(MRD0);
|
||||||
|
digitalWrite(chipSelectPin,HIGH);
|
||||||
|
|
||||||
|
/* Clear the counter i.e. set it to zero */
|
||||||
|
IR = 0x00; /* Clear the instructino register IR */
|
||||||
|
digitalWrite(chipSelectPin,LOW); /* Select chip and initialise transfer */
|
||||||
|
IR |= 0x20; /* Select CNTR: B5=1,B4=0,B3=0; CLR register: B7=0,B6=0 */
|
||||||
|
SPI.transfer(IR); /* Write to instruction register */
|
||||||
|
digitalWrite(chipSelectPin,HIGH);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void recvWithEndMarker()
|
||||||
|
/* Receive data from serial port finishing with "newline" character.
|
||||||
|
Based on http://forum.arduino.cc/index.php?topic=396450 Example 4 */
|
||||||
|
{
|
||||||
|
static byte ndx = 0;
|
||||||
|
char endMarker = '\n';
|
||||||
|
char rc;
|
||||||
|
|
||||||
|
if (Serial.available() > 0) {
|
||||||
|
rc = Serial.read();
|
||||||
|
|
||||||
|
if (rc != endMarker) {
|
||||||
|
receivedChars[ndx] = rc;
|
||||||
|
ndx++;
|
||||||
|
if (ndx >= numChars) {
|
||||||
|
ndx = numChars - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
receivedChars[ndx] = '\0'; // terminate the string
|
||||||
|
ndx = 0;
|
||||||
|
newData = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool convertNewNumber()
|
||||||
|
/* Converts character string to floating point number only if there are new
|
||||||
|
data to convert, otherwise returns false */
|
||||||
|
{
|
||||||
|
if (newData) {
|
||||||
|
dataNumber = 0.0; // new for this version
|
||||||
|
dataNumber = atof(receivedChars); // new for this version
|
||||||
|
newData = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialiseEncoderStateMachine()
|
||||||
|
/* User written code to initialise state of state machine code based on input states */
|
||||||
|
{
|
||||||
|
if (channelAState)
|
||||||
|
{
|
||||||
|
if(channelBState)
|
||||||
|
{
|
||||||
|
state = state3;
|
||||||
|
}
|
||||||
|
/* else.... a lot of code goes here! */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateEncoderStateMachine()
|
||||||
|
/* User written code to update state and increment count of state machine */
|
||||||
|
{
|
||||||
|
channelAState = digitalRead(channelA);
|
||||||
|
channelBState = digitalRead(channelB);
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case state1:
|
||||||
|
if (channelAState && !channelBState)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
state = state2;
|
||||||
|
}
|
||||||
|
/* else if .... a lot of code goes here! */
|
||||||
|
/* don't forget "break" at end of each case. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(TIMER5_OVF_vect )
|
||||||
|
{
|
||||||
|
//when this runs, you had 65536 pulses counted.
|
||||||
|
bigLaps++;
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,37 @@
|
|||||||
|
const int NumStates = 8;
|
||||||
|
int state = 0;
|
||||||
|
byte StateTable [NumStates][2]={
|
||||||
|
{0x88, 1},
|
||||||
|
{0xC8, 2},
|
||||||
|
{0x28, 5},
|
||||||
|
{0x48, 2},
|
||||||
|
{0x88, 1},
|
||||||
|
{0x8C, 2},
|
||||||
|
{0x82, 5},
|
||||||
|
{0x84, 2}};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
DDRA = 0xFF; // Set PORTA as output
|
||||||
|
Serial.begin(9600);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
Serial.print(state);
|
||||||
|
Serial.print(' ');
|
||||||
|
PORTA = StateTable[state][0];
|
||||||
|
Serial.print(PORTA, HEX);
|
||||||
|
Serial.print(' ');
|
||||||
|
Serial.print("Waiting Time is:");
|
||||||
|
Serial.print(StateTable[state][1]);
|
||||||
|
Serial.print('\n');
|
||||||
|
delay(StateTable[state][1]*1000);
|
||||||
|
|
||||||
|
if(state < NumStates-1)
|
||||||
|
{
|
||||||
|
state++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,38 @@
|
|||||||
|
const int NumStates = 8;
|
||||||
|
int state = 0;
|
||||||
|
byte StateTable [NumStates][3]={
|
||||||
|
{0x88, 1, 0},
|
||||||
|
{0xC8, 2, 0},
|
||||||
|
{0x28, 5, 1},
|
||||||
|
{0x48, 2, 0},
|
||||||
|
{0x88, 1, 0},
|
||||||
|
{0x8C, 2, 0},
|
||||||
|
{0x82, 5, 0},
|
||||||
|
{0x84, 2, 0}};
|
||||||
|
void setup() {
|
||||||
|
DDRA = 0xFF; // Set PORTA as output
|
||||||
|
Serial.begin(9600);
|
||||||
|
}
|
||||||
|
void loop() {
|
||||||
|
Serial.print(state);
|
||||||
|
Serial.print(' ');
|
||||||
|
PORTA = StateTable[state][0];
|
||||||
|
Serial.print(PORTA, HEX);
|
||||||
|
Serial.print(' ');
|
||||||
|
Serial.print("Waiting Time is:");
|
||||||
|
Serial.print(StateTable[state][1]);
|
||||||
|
Serial.print('\n');
|
||||||
|
delay(StateTable[state][1]*1000);
|
||||||
|
while(StateTable[state][3] && !(PINB & 0x01));
|
||||||
|
{
|
||||||
|
// Just wait here if StateTable[state][3] = 1 and Pin No 1 on Port B goes low (0).
|
||||||
|
}
|
||||||
|
if(state < NumStates-1)
|
||||||
|
{
|
||||||
|
state++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,15 @@
|
|||||||
|
Fred Bloggs 73
|
||||||
|
Michael Smith 43
|
||||||
|
Claire White 64
|
||||||
|
Simon Black 23
|
||||||
|
Joshua Mason -20
|
||||||
|
Jenny Jones 57
|
||||||
|
George Clark 40
|
||||||
|
Ann Bell 101
|
||||||
|
Fay Allen 52
|
||||||
|
John Morris 60
|
||||||
|
Steven Hayes 47
|
||||||
|
Hannah Jackson 94
|
||||||
|
Alex Benson 50
|
||||||
|
Susan Baker 70
|
||||||
|
Wendy Brooks 57
|
@@ -0,0 +1,36 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define WIDTH 10
|
||||||
|
#define INPUT_BUFFER_LEN 64
|
||||||
|
/// Used to clear the buffer scanf reads from.
|
||||||
|
/// Useful when user enters malformed input, as scanf does not clear
|
||||||
|
/// when it fails to read an input.
|
||||||
|
#define READ_STDIN_UNTIL_NEWLINE() while (getchar() != '\n'){};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int rc, height, i, j;
|
||||||
|
char *input[INPUT_BUFFER_LEN];
|
||||||
|
|
||||||
|
do {
|
||||||
|
printf("Enter height: ");
|
||||||
|
rc = scanf("%d", &height);
|
||||||
|
READ_STDIN_UNTIL_NEWLINE();
|
||||||
|
|
||||||
|
if (rc == 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
for(i = 0; i < height; i++) {
|
||||||
|
for (j = 0; j < i; j++) {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
for (j = 0; j < WIDTH; j++) {
|
||||||
|
printf("#");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,44 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define BUF_LEN 1024
|
||||||
|
|
||||||
|
#define GRADE_FIRST 70
|
||||||
|
#define GRADE_UPPER_SECOND 60
|
||||||
|
#define GRADE_LOWER_SECOND 50
|
||||||
|
#define GRADE_THIRD 40
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int rc, mark;
|
||||||
|
FILE *fp;
|
||||||
|
char buf[BUF_LEN];
|
||||||
|
char first_name[BUF_LEN];
|
||||||
|
char last_name[BUF_LEN];
|
||||||
|
|
||||||
|
fp = fopen("Results.txt", "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
printf("Unable to open file Results.txt\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fgets(buf, BUF_LEN, fp) != NULL) {
|
||||||
|
rc = sscanf(buf, "%s %s\t%d", first_name, last_name, &mark);
|
||||||
|
if (rc != 3) {
|
||||||
|
printf("Failed to read line: %s\n", buf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf("%s %s\t", first_name, last_name);
|
||||||
|
|
||||||
|
if (mark >= GRADE_FIRST) {
|
||||||
|
printf("First\n");
|
||||||
|
} else if (mark >= GRADE_UPPER_SECOND ) {
|
||||||
|
printf("Upper second\n");
|
||||||
|
} else if (mark >= GRADE_LOWER_SECOND) {
|
||||||
|
printf("Lower second\n");
|
||||||
|
} else if (mark >= GRADE_THIRD) {
|
||||||
|
printf("Third\n");
|
||||||
|
} else {
|
||||||
|
printf("Fail\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,59 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define BUF_LEN 1024
|
||||||
|
/// Used to clear the buffer scanf reads from.
|
||||||
|
/// Useful when user enters malformed input, as scanf does not clear
|
||||||
|
/// when it fails to read an input.
|
||||||
|
#define READ_STDIN_UNTIL_NEWLINE() while (getchar() != '\n'){};
|
||||||
|
|
||||||
|
|
||||||
|
int cone_volume(float *volume, float radius, float height) {
|
||||||
|
if (radius < 0.0 || height < 0.0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*volume = M_PI*radius*radius*height/3.0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cone_area(float *area, float radius, float height) {
|
||||||
|
if (radius < 0.0 || height < 0.0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*area = M_PI*radius*(radius + sqrt(radius*radius + height*height));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int rc;
|
||||||
|
float result, height, radius;
|
||||||
|
char buf[BUF_LEN];
|
||||||
|
|
||||||
|
do {
|
||||||
|
printf("Enter radius of cone: ");
|
||||||
|
rc = scanf("%f", &radius);
|
||||||
|
READ_STDIN_UNTIL_NEWLINE();
|
||||||
|
} while(rc != 1 && radius < 0.0);
|
||||||
|
|
||||||
|
do {
|
||||||
|
printf("Enter height of cone: ");
|
||||||
|
rc = scanf("%f", &height);
|
||||||
|
READ_STDIN_UNTIL_NEWLINE();
|
||||||
|
} while(rc != 1 && height < 0.0);
|
||||||
|
|
||||||
|
rc = cone_area(&result, radius, height);
|
||||||
|
if(rc != 0) {
|
||||||
|
printf("Unable to calculate surface area\n");
|
||||||
|
} else {
|
||||||
|
printf("Surface area: %.3f\n", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = cone_volume(&result, radius, height);
|
||||||
|
if(rc != 0) {
|
||||||
|
printf("Unable to calculate volume\n");
|
||||||
|
} else {
|
||||||
|
printf("Volume: %.3f\n", result);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,4 @@
|
|||||||
|
CFLAGS=-lm
|
||||||
|
|
||||||
|
%.c:
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $*
|
@@ -0,0 +1,15 @@
|
|||||||
|
Fred Bloggs 73
|
||||||
|
Michael Smith 43
|
||||||
|
Claire White 64
|
||||||
|
Simon Black 23
|
||||||
|
Joshua Mason -20
|
||||||
|
Jenny Jones 57
|
||||||
|
George Clark 40
|
||||||
|
Ann Bell 101
|
||||||
|
Fay Allen 52
|
||||||
|
John Morris 60
|
||||||
|
Steven Hayes 47
|
||||||
|
Hannah Jackson 94
|
||||||
|
Alex Benson 50
|
||||||
|
Susan Baker 70
|
||||||
|
Wendy Brooks 57
|
Binary file not shown.
After Width: | Height: | Size: 352 KiB |
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,27 @@
|
|||||||
|
12
|
||||||
|
0
|
||||||
|
12.343
|
||||||
|
1
|
||||||
|
13.574
|
||||||
|
2
|
||||||
|
14.359
|
||||||
|
3
|
||||||
|
14.367
|
||||||
|
4
|
||||||
|
15.694
|
||||||
|
5
|
||||||
|
17.489
|
||||||
|
6
|
||||||
|
19.486
|
||||||
|
7
|
||||||
|
20.427
|
||||||
|
8
|
||||||
|
21.759
|
||||||
|
9
|
||||||
|
20.402
|
||||||
|
10
|
||||||
|
19.444
|
||||||
|
11
|
||||||
|
18.736
|
||||||
|
12
|
||||||
|
17.445
|
BIN
uni/mmme/3085_computer_engineering_and_mechatronics/past_papers/21-22/code/1
Executable file
BIN
uni/mmme/3085_computer_engineering_and_mechatronics/past_papers/21-22/code/1
Executable file
Binary file not shown.
@@ -0,0 +1,80 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define BUF_SIZE (size_t) 4096
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int time_seconds;
|
||||||
|
float temperature;
|
||||||
|
} Datum;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int rc, i, data_size;
|
||||||
|
char buf[BUF_SIZE+1];
|
||||||
|
char *rc_cp;
|
||||||
|
FILE *fp;
|
||||||
|
Datum *data;
|
||||||
|
|
||||||
|
printf("Enter filename of temperature data: ");
|
||||||
|
rc = scanf("%s", buf);
|
||||||
|
// scanf return number of successfully scanned items
|
||||||
|
if (rc != 1) {
|
||||||
|
printf("Unable to read input\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen(buf, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
printf("Unable to open file '%s' for reading\n", buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_cp = fgets(buf, BUF_SIZE, fp);
|
||||||
|
if (rc_cp == NULL) {
|
||||||
|
printf("Unable to read first line of file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sscanf(buf, "%d", &data_size);
|
||||||
|
if (rc != 1) {
|
||||||
|
printf("Unable to parse first line of file as integer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = (Datum*) malloc(data_size * sizeof(Datum));
|
||||||
|
|
||||||
|
for(i = 0; i < data_size; i++) {
|
||||||
|
rc_cp = fgets(buf, BUF_SIZE, fp);
|
||||||
|
if (rc_cp == NULL) {
|
||||||
|
printf("Unexpected EOF or file read error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sscanf(buf, "%d", &data[i].time_seconds);
|
||||||
|
if (rc != 1) {
|
||||||
|
printf("Unable to parse line as time (integer): %s\n", buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_cp = fgets(buf, BUF_SIZE, fp);
|
||||||
|
if (rc_cp == NULL) {
|
||||||
|
printf("Unexpected EOF or file read error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sscanf(buf, "%f", &data[i].temperature);
|
||||||
|
if (rc != 1) {
|
||||||
|
printf("Unable to parse line as temperature (float): %s\n", buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Time/s\tTemperature\n");
|
||||||
|
for(i = 0; i < data_size; i++) {
|
||||||
|
printf("%d\t%.2f\n", data[i].time_seconds, data[i].temperature);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
uni/mmme/3085_computer_engineering_and_mechatronics/past_papers/21-22/code/2
Executable file
BIN
uni/mmme/3085_computer_engineering_and_mechatronics/past_papers/21-22/code/2
Executable file
Binary file not shown.
@@ -0,0 +1,54 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define CLR_STDIN() while(getchar() != '\n'){}
|
||||||
|
|
||||||
|
/// Calculate kinetic energy of object
|
||||||
|
///
|
||||||
|
/// *e - pointer to store calculated energy in
|
||||||
|
/// m - mass of object, must be greater than 0
|
||||||
|
/// v - velocity of object
|
||||||
|
///
|
||||||
|
/// Returns 1 on success, 0 on failure
|
||||||
|
int calculate_kinetic_energy(float *e, float m, float v) {
|
||||||
|
// cannot have negative mass
|
||||||
|
if (m <= 0.0) return 0;
|
||||||
|
|
||||||
|
*e = 0.5 * m * v * v;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int rc;
|
||||||
|
float e, m = 0.0, v = 0.0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
printf("Enter mass of object: ");
|
||||||
|
rc = scanf("%f", &m);
|
||||||
|
CLR_STDIN();
|
||||||
|
if (rc != 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} while (m <= 0.0);
|
||||||
|
|
||||||
|
do {
|
||||||
|
printf("Enter velocity of object: ");
|
||||||
|
rc = scanf("%f", &v);
|
||||||
|
CLR_STDIN();
|
||||||
|
if (rc != 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
rc = calculate_kinetic_energy(&e, m, v);
|
||||||
|
if (rc != 1) {
|
||||||
|
printf("calculate_kinetic_energy failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Kinetic energy: %.3f kJ\n", e/1000);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -0,0 +1 @@
|
|||||||
|
The quick brown fox jumped over the lazy dog!
|
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user