Skip to content

Commit f07f6dd

Browse files
committed
Work on nitrate sensor
1 parent 65a213e commit f07f6dd

File tree

5 files changed

+248
-7227
lines changed

5 files changed

+248
-7227
lines changed

Nitrate Sensor/nitrate_sensor.scad

+139-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,139 @@
1-
# Nitrate sensor
1+
// Nitrate sensor
2+
//
3+
// This is housing for an optical nitrate sensor that's meant to hang out underwater.
4+
//
5+
// There are two main parts: The emitter module and the photodiode module.
6+
// Both sit behind quartz discs that allow UV light to pass through.
7+
8+
quartz_radius = 5 + 0.1; // Radius of quartz disc, plus a bit extra for tolerance
9+
quartz_thickness = 0.8; // Thickness of quartz disc
10+
wall_thickness = 1.2;
11+
gap_distance = 10; // Gap between emitter and photodiode
12+
extra_height = 5;
13+
base_height = 3; // Height of base
14+
compartment_height = 20; // Height of compartment (enough to fit electronics)
15+
16+
x = 100/2;
17+
y = 63/2;
18+
19+
r = quartz_radius;
20+
t = wall_thickness;
21+
g = gap_distance;
22+
$fn = 50;
23+
24+
translate([0, 0, base_height]) difference() {
25+
base();
26+
carveout();
27+
emitter_negatives();
28+
}
29+
30+
union() {
31+
h = compartment_height;
32+
translate([0, x + 20, h]) {
33+
difference() {
34+
compartment(1, h);
35+
translate([0, 0, 1]) compartment(0, h);
36+
screw_holes(h, 2);
37+
}
38+
translate([0, 0, 0]) difference() {
39+
screw_holes(h-1, 3);
40+
screw_holes(h-1, 1);
41+
}
42+
}
43+
44+
}
45+
46+
module base() {
47+
r = 25;
48+
h = base_height;
49+
p = 15;
50+
51+
52+
difference() {
53+
hull() {
54+
compartment();
55+
emitters();
56+
}
57+
// compartment(-1);
58+
translate([0, 0, -1]) difference() {
59+
scale([0.85, 0.8, 1]) hull() {
60+
compartment();
61+
emitters(-5);
62+
}
63+
hull() {
64+
scale([1.3, 1, 1]) carveout();
65+
translate([0, 0, -100]) scale([1.3, 100, 1]) carveout();
66+
}
67+
}
68+
69+
translate([0, 0, -1]) screw_holes(h-1, 0.8);
70+
}
71+
}
72+
73+
module compartment(o=0, h=base_height) {
74+
r = 2;
75+
translate([0, 0, -h]) linear_extrude(h) {
76+
hull() offset(o) {
77+
translate([x, y]) circle(r);
78+
translate([-x, y]) circle(r);
79+
translate([x, -y]) circle(r);
80+
translate([-x, -y]) circle(r);
81+
}
82+
}
83+
}
84+
85+
module screw_holes(h, r=2) {
86+
translate([0, 0, -h]) linear_extrude(h) {
87+
union() {
88+
translate([x, y]) circle(r);
89+
translate([-x, y]) circle(r);
90+
translate([x, -y]) circle(r);
91+
translate([-x, -y]) circle(r);
92+
}
93+
}
94+
}
95+
96+
module carveout() {
97+
h = gap_distance;
98+
r = r + 4;
99+
translate([-h/2, 0, 10]) rotate([0, 90, 0]) scale([1,2,1]) cylinder(h, r=r);
100+
}
101+
102+
module emitters(extra_distance=0) {
103+
translate([0, 0, extra_height]) {
104+
emitter_housing(extra_distance);
105+
mirror([1, 0, 0]) emitter_housing(extra_distance);
106+
}
107+
}
108+
109+
module emitter_negatives() {
110+
translate([0, 0, extra_height]) {
111+
emitter_housing_cutouts();
112+
mirror([1, 0, 0]) emitter_housing_cutouts();
113+
}
114+
}
115+
116+
module emitter_housing(extra_distance) {
117+
h1 = 10; // body height
118+
h2 = 1.5; // cap height
119+
h3 = quartz_thickness;
120+
121+
translate([-h1-h2-g+extra_distance/2, 0, r+t]) rotate([0, 90]) {
122+
hull() {
123+
cylinder(h1, r=r+t);
124+
translate([0, 0, h1]) cylinder(h2, r=r+t - 0.5);
125+
}
126+
}
127+
}
128+
129+
module emitter_housing_cutouts(h1=10, h2=1.5, h3=quartz_thickness) {
130+
h1 = 10; // body height
131+
h2 = 1.5; // cap height
132+
h3 = quartz_thickness;
133+
134+
translate([-h1-h2-g/2, 0, r+t]) rotate([0, 90]) {
135+
cylinder(h1, r=r);
136+
translate([0, 0, h1]) cylinder(h2, r=r-1);
137+
translate([0, 0, h1+h2-h3]) cylinder(h2, r=r);
138+
}
139+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
Using the AMS AS7331 Spectral UV Sensor in Command/One Shot (CMD) Mode.
3+
4+
This example shows how operate the AS7331 in the default CMD mode. The start
5+
command is sent, then delays until the conversion time has passed before
6+
reading out the UV values.
7+
8+
By: Alex Brudner
9+
SparkFun Electronics
10+
Date: 2023/11/17
11+
SparkFun code, firmware, and software is released under the MIT License.
12+
Please see LICENSE.md for further details.
13+
14+
Hardware Connections:
15+
IoT RedBoard --> AS7331
16+
QWIIC --> QWIIC
17+
18+
Serial.print it out at 115200 baud to serial monitor.
19+
20+
Feel like supporting our work? Buy a board from SparkFun!
21+
https://www.sparkfun.com/products/23517 - Qwiic 1x1
22+
https://www.sparkfun.com/products/23518 - Qwiic Mini
23+
*/
24+
25+
#include <Arduino.h>
26+
#include <Wire.h>
27+
#include <SparkFun_AS7331.h>
28+
#include "heltec.h"
29+
30+
SfeAS7331ArdI2C myUVSensor;
31+
32+
void setup() {
33+
Heltec.begin(true /*DisplayEnable Enable*/, false /*LoRa Disable*/, true /*Serial Enable*/);
34+
Serial.begin(115200);
35+
delay(2000);
36+
while (!Serial) { delay(100); };
37+
38+
Serial.println("AS7331 UV A/B/C Command (One-shot) mode Example.");
39+
Heltec.display->init();
40+
Heltec.display->setFont(ArialMT_Plain_16);
41+
Heltec.display->flipScreenVertically();
42+
Heltec.display->clear();
43+
44+
Wire1.begin(3, 4); // SDA on GPIO3, SCL on GPIO4
45+
46+
// Initialize sensor and run default setup.
47+
if (myUVSensor.begin(kDefaultAS7331Addr, Wire1) == false) {
48+
Serial.println("Sensor failed to begin. Please check your wiring!");
49+
Serial.println("Halting...");
50+
while (1);
51+
}
52+
53+
setupGain();
54+
Serial.println("Sensor began.");
55+
56+
// Set measurement mode and change device operating mode to measure.
57+
if (myUVSensor.prepareMeasurement(MEAS_MODE_CMD) == false) {
58+
Serial.println("Sensor did not get set properly.");
59+
Serial.println("Halting...");
60+
while (1)
61+
;
62+
}
63+
64+
Serial.println("Set mode to command.");
65+
}
66+
67+
void setupGain() {
68+
as7331_gain_t desiredGain = GAIN_16;
69+
sfeTkError_t result = myUVSensor.setGain(desiredGain);
70+
if (result != kSTkErrOk) {
71+
Serial.println("Failed to set gain!");
72+
// Handle the error, e.g., retry or use a default gain setting
73+
} else {
74+
Serial.println("Gain set successfully.");
75+
}
76+
}
77+
78+
void loop() {
79+
80+
// Send a start measurement command.
81+
82+
83+
if (kSTkErrOk != myUVSensor.setStartState(true))
84+
Serial.println("Error starting reading!");
85+
86+
// Wait for a bit longer than the conversion time.
87+
delay(2 + myUVSensor.getConversionTimeMillis());
88+
89+
// Read UV values.
90+
if (kSTkErrOk != myUVSensor.readAllUV())
91+
Serial.println("Error reading UV.");
92+
93+
// Serial.print("UVA:");
94+
// Serial.print(myUVSensor.getUVA());
95+
// Serial.print(" UVB:");
96+
// Serial.print(myUVSensor.getUVB());
97+
// Serial.print(" UVC:");
98+
// Serial.println(myUVSensor.getUVC());
99+
String output = String(myUVSensor.getUVA()) + ", " + String(myUVSensor.getUVB()) + ", " + String(myUVSensor.getUVC());
100+
Serial.println(output);
101+
display(output);
102+
delay(200);
103+
}
104+
105+
void display(String message) {
106+
Heltec.display->clear();
107+
Heltec.display->drawString(3, 15, message);
108+
Heltec.display->display();
109+
}
951 KB
Binary file not shown.

Nitrate Sensor/nitrate_sensor_top.stl

276 KB
Binary file not shown.

0 commit comments

Comments
 (0)