166 lines
5.2 KiB
TypeScript
166 lines
5.2 KiB
TypeScript
let sensorType: string
|
|
|
|
// ANALOG or TILT
|
|
sensorType = "TILT"
|
|
while (true) {
|
|
// splash screen (flood monitor)
|
|
basic.showLeds(`
|
|
# # # . .
|
|
# . . . .
|
|
# # . # .
|
|
# . . # .
|
|
# . . # #
|
|
`)
|
|
while (true) {
|
|
if (input.buttonIsPressed(Button.A)) {
|
|
// test that the sensor works
|
|
testMode()
|
|
break
|
|
} else if (input.buttonIsPressed(Button.B)) {
|
|
// run the real flood monitor
|
|
floodMonitor()
|
|
break
|
|
} else {
|
|
basic.pause(100)
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* test mode - test that the monitor and buzzer work
|
|
* no filtering in this mode, direct screen update
|
|
*/
|
|
function testMode() {
|
|
basic.showLeds(`
|
|
# # # # #
|
|
. . # . .
|
|
. . # . .
|
|
. . # . .
|
|
. . # . .
|
|
`)
|
|
waitNoButtons()
|
|
let img = images.createImage(`
|
|
. . . . . . . . . . . . . . . . . . . . # # # # #
|
|
. . . . . . . . . . . . . . . # # # # # . . . . .
|
|
. . . . . . . . . . # # # # # . . . . . . . . . .
|
|
. . . . . # # # # # . . . . . . . . . . . . . . .
|
|
# # # # # . . . . . . . . . . . . . . . . . . . .
|
|
`)
|
|
while (!input.buttonIsPressed(Button.A)) {
|
|
// Show live reading on display
|
|
let value = readSensor()
|
|
img.showImage(value * 5)
|
|
// Turn beeper on only if maximum value seen
|
|
if (value >= 4) {
|
|
pins.digitalWritePin(DigitalPin.P1, 1)
|
|
} else {
|
|
pins.digitalWritePin(DigitalPin.P1, 0)
|
|
}
|
|
basic.pause(50)
|
|
}
|
|
waitNoButtons()
|
|
}
|
|
|
|
function floodMonitor() {
|
|
basic.showLeds(`
|
|
# . . . #
|
|
# # . # #
|
|
# . # . #
|
|
# . . . #
|
|
# . . . #
|
|
`)
|
|
waitNoButtons()
|
|
let line = images.createImage(`
|
|
. . . . . . . . . . . . . . . . . . . . # # # # #
|
|
. . . . . . . . . . . . . . . # # # # # . . . . .
|
|
. . . . . . . . . . # # # # # . . . . . . . . . .
|
|
. . . . . # # # # # . . . . . . . . . . . . . . .
|
|
# # # # # . . . . . . . . . . . . . . . . . . . .
|
|
`)
|
|
let state = "SAFE"
|
|
let averagedValue = 0
|
|
while (!input.buttonIsPressed(Button.A)) {
|
|
let value = readSensor()
|
|
// Apply some 'lag' filtering to the value, so that 'bobbing' doesn't set off alarm
|
|
// i.e. to go from 0 to 4 takes 4 times round the loop
|
|
if (value > averagedValue) {
|
|
// On the way up, changes in reading are slowed down
|
|
averagedValue = averagedValue + 1
|
|
} else if (value < averagedValue) {
|
|
// On the way down, changes in reading happen immediately
|
|
averagedValue = value
|
|
}
|
|
// Work out what to do based on the averaged value (non bobbing value)
|
|
if (state == "SAFE") {
|
|
if (averagedValue >= 4) {
|
|
pins.digitalWritePin(DigitalPin.P1, 1)
|
|
state = "ALARMING"
|
|
} else {
|
|
// Display raw value as a line
|
|
line.showImage(value * 5)
|
|
// fill in based on averaged value (long term reading)
|
|
for (let i = 0; i < averagedValue; i++) {
|
|
led.plot(2, 4 - i)
|
|
}
|
|
}
|
|
} else if (state == "ALARMING") {
|
|
if (input.buttonIsPressed(Button.B)) {
|
|
pins.digitalWritePin(DigitalPin.P1, 0)
|
|
state = "SAFE"
|
|
} else {
|
|
basic.showAnimation(`
|
|
# # # # # . . . . .
|
|
# # # # # . . . . .
|
|
# # # # # . . . . .
|
|
# # # # # . . . . .
|
|
# # # # # . . . . .
|
|
`, 400)
|
|
}
|
|
}
|
|
basic.pause(300)
|
|
}
|
|
waitNoButtons()
|
|
}
|
|
|
|
/**
|
|
* Read a value 0,1,2,3,4 from either ANALOG or TILT
|
|
*/
|
|
function readSensor(): number {
|
|
let value = 0
|
|
// Produce a sensor value in range 0..1023
|
|
if (sensorType == "ANALOG") {
|
|
// Input range is 0..1023
|
|
value = pins.analogReadPin(AnalogPin.P0)
|
|
} else if (sensorType == "TILT") {
|
|
// Input range is -1024 (pads highest)..1023 (pads lowest)
|
|
value = input.acceleration(Dimension.Y)
|
|
// Emulator sometimes returns out of range values, so clamp to expected range
|
|
value = Math.clamp(-1024, 1023, value)
|
|
// Convert to an entirely positive range from 0 pads full up to 2047 pads full down
|
|
// (hinged at the 'eyes' end)
|
|
value = value + 1024
|
|
// Invert the direction, so that "pads up" is largest, "pads down" is smallest
|
|
value = 2047 - value
|
|
// We want the same range as the analog, so halve the range
|
|
value = value / 2
|
|
}
|
|
// 5 possible values (0,1,2,3,4) based on sensible thresholds
|
|
// We do this by thresholds, so that we have more control over the 5 levels
|
|
if (value < 200) {
|
|
return 0
|
|
} else if (value < 400) {
|
|
return 1
|
|
} else if (value < 600) {
|
|
return 2
|
|
} else if (value < 800) {
|
|
return 3
|
|
}
|
|
return 4
|
|
}
|
|
|
|
function waitNoButtons() {
|
|
while (input.buttonIsPressed(Button.A) || input.buttonIsPressed(Button.B)) {
|
|
basic.pause(100)
|
|
}
|
|
}
|