Jump to content

Gina

Beyond the Event Horizon
  • Posts

    45,326
  • Joined

  • Last visited

  • Days Won

    120

Everything posted by Gina

  1. Ah yes, lost connection delays could cause a problem and yes, using counting rather than timing would be better. The actual timing of messages is not important but getting them right is.
  2. It's still doing it!! Got up to 4mph and then crashed back to zero!!
  3. Well, the test sketch is not showing the problem I'm getting with the real thing!! That seems to prove the problem is not with the calculations but there is a problem none the less!! The direction calculations are still running and everything is the same as the real thing except I'm simulating the anemometer pulses. The only thing I can think of trying is to set up all the dials and graphs as the real thing in a Test tab on the Dashboard. One other thing occurs to me - everything was fine with the display for a couple of days so I'm wondering if there is something time related. I guess I could reset the real wind client by powering down and back up again. Here's the current Wind display before I shut it down.
  4. Well, I guess it isn't too bad but it isn't right so it fails the test. Timing variations might explain the Gust speed varying between 12 and 13. The Mean Speed is supposed to be displayed in tenths but I may have used int as speed to the nearest mph is good enough. Think I'll try a large increase in wind speed and see if serious errors arise. I'll go to 200ms next - 5pps = 5x4.5mph = 22.5mph. I would expect the speed to show as 22 or 23.
  5. Problem showing. Mean Speed rose to 11mph rather than 12 then dropped back to 10. Continuing the test at this simulated wind speed.
  6. Realised that since I am running a test simulation with the ESP32 powered from the USB, I can use the Serial Monitor to see results - easier that setting up a load of Node_RED stuff. Testing at 1pps which is about 4.5 mph ATM. Mean Speed reads 4.0mph. Testing at 2pps = 9mph. Mean Speed reads 9.0mph. Testing at 12mph which is 375ms period. Mean Speed reads 11.0mph.
  7. OTOH if the fault is in the code, generating a simulated interrupt within the same ESP32 should have the desired effect but if the problem is internal timing issues it might not. The interrupt handler should have no problem with interrupts at the sort of rate we have here. All it does is increment the PulseCount. // Checks if Hall sensor was triggered - Interrupt Handler void IRAM_ATTR HallTriggered() { // Serial.println("Hall Triggered"); ++PulseCount; // Increment count } So if I produce code to increment the PulseCount at a variable rate it should do the same thing. I think the easiest way would be to add another period to the list with the period set in millis. void loop() { if (!client.connected()) {reconnect();} client.loop(); // time the various periods long now = millis(); if(now - lastP > Ptest) {++PulseCount; lastP = now;} if(now - last3s > P3s) {do3sJobs(); last3s = now;} if(now - last1m > P1m) {do1mJobs(); last1m = now;} if(now - last3m > P3m) {do3mJobs(); last3m = now;} }
  8. I'm now looking into a way of simulating the anemometer in a test rig indoors. Whilst I could do the testing all in one ESP32, I think it would be more realistic to use a separate source of pulses to feed the test ESP32. One way is to use another ESP32 to generate the pulses either using a pot to vary the pulse rate or even set up as another client connected to the MQTT network where an input to the Node-RED Dashboard could set the frequency. Using MQTT would mean I would have an exact control of the pulse rate.
  9. This is the latest Wind display still showing the problem, which isn't surprising as the wind is still a moderate breeze - I estimate around Force 3-4, possibly gusting 5 looking at the trees. This is the large oak trees at the bottom of the next field and a lot higher than my wind instruments so I'm not surprised that the Gusts are less strong at me anemometer. I would say the Gust speed reading is reasonable.
  10. Printing is going well, the O rings and new dome have arrived.
  11. This may answer my queries :- ArduinoOTA ESP32: Wi-Fi (OTA) Wireless Update from the Arduino IDE
  12. The meanArray should be fully loaded after the initial startup, with new entries simply overwriting the oldest entry. It shouldn't be "reset to zero" (emptied) and nor should the new entries be zero. Found this :- ESP8266 Over The Air (OTA) Programming In Arduino IDE A couple of points. I presume it's the same for the ESP32. I have a later Python on my machine. The tutorial shows the Windows version and I only have Linux (Mint)
  13. An interesting departure from topic 😁 Though not entirely unrelated. The problem has been there overnight and still bad. I have been through the calculations and can't find any "overloaded" numeric types. I plan to set up another ESP32 for testing as the running one is up inside the wind unit and would require everything taking down and bringing the"works" indoors to update or swap ESP32s.
  14. // MQTT for wind sensors /********* Rui Santos Complete project details at https://randomnerdtutorials.com ******** Modified and added to by Gina 2020-08-21 onward ******** */ // periods or intervals in milliseconds const int P3s = 3000; // integer const int P1m = 60000u; // unsigned integer const int P3m = 180000ul; // unsigned long long last3s = 0; long last1m = 0; long last3m = 0; // 10m averaging etc. int meanArray[10] = {0,0,0,0,0,0,0,0,0,0}; int gustArray[10] = {0,0,0,0,0,0,0,0,0,0}; int ringIndex = 0; // Output variables int meanSpeed = 0; // 0-100mph int gustSpeed = 0; // 0-100mph // Set GPIO for Hall Sensor const int HallSensorPin = 4; int PulseCount = 0, windGust = 0; float windSpeed = 0; #include <WiFi.h> #include <PubSubClient.h> // Replace the next variables with your SSID/Password combination const char* ssid = "Ubiquity"; const char* password = "********"; const char* mqtt_server = "192.168.1.140"; WiFiClient windClient; PubSubClient client(windClient); char msg[50]; int value = 0; // Checks if Hall sensor was triggered - Interrupt Handler void IRAM_ATTR HallTriggered() { // Serial.println("Hall Triggered"); ++PulseCount; // Increment count } int Beaufort(int mph){ if (mph < 1) return 0; else if (mph <= 3) return 1; else if (mph <= 7) return 2; else if (mph <= 12) return 3; else if (mph <= 18) return 4; else if (mph <= 24) return 5; else if (mph <= 31) return 6; else if (mph <= 38) return 7; else if (mph <= 46) return 8; else if (mph <= 54) return 9; else if (mph <= 63) return 10; else if (mph <= 72) return 11; else return 12; } void setup() { Serial.begin(115200); setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(callback); // Hall Sensor mode INPUT_PULLUP pinMode(HallSensorPin, INPUT_PULLUP); // Set HallSensor pin as interrupt, assign interrupt function and set FALLING mode attachInterrupt(digitalPinToInterrupt(HallSensorPin), HallTriggered, FALLING); } void setup_wifi() { delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void callback(char* topic, byte* message, unsigned int length) { Serial.print("Message arrived on topic: "); Serial.print(topic); Serial.print(". Message: "); String messageTemp; for (int i = 0; i < length; i++) { Serial.print((char)message[i]); messageTemp += (char)message[i]; } Serial.println(); } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect("windClient")) { Serial.println("connected"); // Subscribe } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } // void sendSpeedMessages(){ // messages to send :- // wind/speed/mph -- meanSpeed // wind speed/force -- Beaufort(meanSpeed) // wind/gust/mph -- gustSpeed // wind/gust/force -- Beaufort(gustSpeed) // // Convert the Mean Speed to a char array char msString[8]; dtostrf(meanSpeed, 1, 1, msString); client.publish("wind/speed/mph", msString); // Convert the Mean-Speed-Force to a char array char bsString[8]; dtostrf(Beaufort(meanSpeed), 1, 0, bsString); client.publish("wind/speed/force", bsString); // Convert the Gust-Speed to a char array char gsString[8]; dtostrf(gustSpeed, 1, 0, gsString); client.publish("wind/gust/mph", gsString); // Convert the Gust-Speed-Force to a char array char bgString[8]; dtostrf(Beaufort(gustSpeed), 1, 0, bgString); client.publish("wind/gust/force", bgString); } // Debugging only void sendNumberMessage(int N){ // Convert the number to a char array char numString[8]; dtostrf(N, 1, 0, numString); Serial.print("Number: "); Serial.println(numString); client.publish("wind/number", numString); } void sendNumberMessage2(int N){ // Convert the number to a char array char numString[8]; dtostrf(N, 1, 0, numString); Serial.print("Number: "); Serial.println(numString); client.publish("wind/number2", numString); } // void do3sJobs (){ windSpeed += PulseCount; // Accumulate mean speed if (PulseCount > windGust) {windGust = PulseCount;}; // Get max speed for gust PulseCount = 0; } void do1mJobs(){ // wind speed mean and gust ring arrays and report meanArray[ringIndex] = windSpeed; // put windSpeed into new array index gustArray[ringIndex] = windGust; // put windGust into new array index // windSpeed /=13; // /20 and *1.5 -- leave this for later meanSpeed = 0; gustSpeed = 0; windSpeed = 0; windGust = 0; for (int i = 0; i < 10; i++) { meanSpeed += meanArray[i]; // sum the windSpeeds if (gustArray[i] > gustSpeed){gustSpeed = gustArray[i];}; // find maximum gust speed } meanSpeed /=133; // the first sum was over 20 values and then the second over 10 values gustSpeed *= 1.5; // Speed count over 3s rather than 4.5s sendSpeedMessages(); // sendNumberMessage(ringIndex); debugging only ringIndex = (ringIndex+1)%10; // move ringIndex on to next location in the ring arrays } void do3mJobs(){ } void loop() { if (!client.connected()) {reconnect();} client.loop(); // time the various periods long now = millis(); if(now - last3s > P3s) {do3sJobs(); last3s = now;} if(now - last1m > P1m) {do1mJobs(); last1m = now;} if(now - last3m > P3m) {do3mJobs(); last3m = now;} }
  15. It seems to have got worse. I may try copying the wind speed code onto another ESP32 and feeding it with varying frequency pulses and see what happens as the pulse rate is increased. I can add in code to send various numbers to the MQTT network to see what's happening.
  16. This small redesign only allows for the new dome mounting and not remote focussing or remote controlled cover. The aim is to get the ASC working again ASAP. I can work on a major change with remote focussing and dome cover in easy time without the pressure of wanting the ASC in use.
  17. The three new parts have now been "sliced" and ready for 3D printing tomorrow. I've ordered a new dome as the old one has silicone sealant on it which I can't get off and this would spoil the seal with the O ring.
  18. New camera housing and dome flange. This part goes on top and covers the top of the camera for thermal insulation and also carries the dew heater. Plus it holds the O ring in position.
  19. Somewhere in that code must be an error but I've been through it many times and can't see it. It is probably a case of three sevens are twenty two - you can go over calculations or code many times and the error remains invisible. Many years ago when I was programming I would go through the code bit by bit and explain what it was doing to my friend. Sometimes I would then find the problem myself or she would. She knew practically nothing about coding but was an enormous help.
  20. I think the problem is probably in the sketch so I'm continuing here. Since the problem seems it might be to do with the increased breeze today I'm wondering if I'm exceeding the capacity of a numeric type somewhere. I thought I allowed plenty of headroom but maybe not. I'm seeing gusts up to 13mph with mean speed up to 10mph. Let's go over the process in detail. The anemometer produces one count per revolution and one pulse per second for 4.5mph ie. 3 pulses in the 3s Gust interval. I thought I had designed the code to take speed up to 100mph. At that hopefully highly unlikely speed we would get 67 pulses per sec. (2/3 of 100.) First integration period is 1m so 20 times the 3s period and 60x100x2/3 counts. That's 4,000 counts. Then we put that into the 10 integer ring array. So far so good. Definitely no overload. Next, the mean speed over 10m is calculated by summing the 10 ring array locations (before dividing to get the mean). Now a mean wind speed of 100mph would produce a sum of 10x400 = 40,000. Oops > 32,767 BUT we aren't getting 100mph winds and this would be alright for a speed up to 100x32767/40000 = 81.9 mph. I can't see a problem with the wind speeds I'm getting today. Think I'll post the complete sketch and maybe someone can look through it and find my error. // MQTT for wind sensors /********* Rui Santos Complete project details at https://randomnerdtutorials.com ******** Modified and added to by Gina 2020-08-21 onward ******** */ // periods or intervals in milliseconds const int P3s = 3000; // integer const int P1m = 60000u; // unsigned integer const int P3m = 180000ul; // unsigned long long last3s = 0; long last1m = 0; long last3m = 0; // ADC pins const int An1 = 34; const int An2 = 35; const int An3 = 32; const int An4 = 33; // ADC readings int dir1 = 0; int dir2 = 0; int dir3 = 0; int dir4 = 0; // Gray to binary table int codeArray[16] = {0,1,3,2,7,6,4,5,15,14,12,13,8,9,11,10}; int dirn = 0; // Direction count bins int bin[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Direction compass Points - not used String CPt[16] = {"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"}; */ // 10m averaging etc. int meanArray[10] = {0,0,0,0,0,0,0,0,0,0}; int gustArray[10] = {0,0,0,0,0,0,0,0,0,0}; int ringIndex = 0; // Output variables int Direction = 0; // 0-359 degrees int meanSpeed = 0; // 0-100mph int gustSpeed = 0; // 0-100mph // Set GPIO for Hall Sensor const int HallSensorPin = 4; int PulseCount = 0, windGust = 0; float windSpeed = 0; #include <WiFi.h> #include <PubSubClient.h> // Replace the next variables with your SSID/Password combination const char* ssid = "Ubiquity"; const char* password = "********"; const char* mqtt_server = "192.168.1.140"; WiFiClient windClient; PubSubClient client(windClient); char msg[50]; int value = 0; // Checks if Hall sensor was triggered - Interrupt Handler void IRAM_ATTR HallTriggered() { // Serial.println("Hall Triggered"); ++PulseCount; // Increment count } int Beaufort(int mph){ if (mph < 1) return 0; else if (mph <= 3) return 1; else if (mph <= 7) return 2; else if (mph <= 12) return 3; else if (mph <= 18) return 4; else if (mph <= 24) return 5; else if (mph <= 31) return 6; else if (mph <= 38) return 7; else if (mph <= 46) return 8; else if (mph <= 54) return 9; else if (mph <= 63) return 10; else if (mph <= 72) return 11; else return 12; } void setup() { Serial.begin(115200); setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(callback); // Hall Sensor mode INPUT_PULLUP pinMode(HallSensorPin, INPUT_PULLUP); // Set HallSensor pin as interrupt, assign interrupt function and set FALLING mode attachInterrupt(digitalPinToInterrupt(HallSensorPin), HallTriggered, FALLING); } void setup_wifi() { delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void callback(char* topic, byte* message, unsigned int length) { Serial.print("Message arrived on topic: "); Serial.print(topic); Serial.print(". Message: "); String messageTemp; for (int i = 0; i < length; i++) { Serial.print((char)message[i]); messageTemp += (char)message[i]; } Serial.println(); } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect("windClient")) { Serial.println("connected"); // Subscribe } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } //Get instantaneous wind direction - variable dirn int readDirection(){ // Read wind vane optical sensor values dir1 = analogRead(An1); dir2 = analogRead(An2); dir3 = analogRead(An3); dir4 = analogRead(An4); // Convert Gray bits to integer int Gray = 0; if (dir1 > 2000) {Gray = 8;}; if (dir2 > 2000) {Gray += 4;}; if (dir3 > 2000) {Gray += 2;}; if (dir4 > 2000) {Gray += 1;}; // Convert Gray to binary dirn = 15 - codeArray[Gray]; // correct rotation direction dirn = (dirn - 1) %16; // correct encoder for North return dirn; } // void sendSpeedMessages(){ // messages to send :- // wind/speed/mph -- meanSpeed // wind speed/force -- Beaufort(meanSpeed) // wind/gust/mph -- gustSpeed // wind/gust/force -- Beaufort(gustSpeed) // // Convert the Mean Speed to a char array char msString[8]; dtostrf(meanSpeed, 1, 1, msString); // Serial.print("Mean Speed: "); // Serial.println(msString); client.publish("wind/speed/mph", msString); // Convert the Mean-Speed-Force to a char array char bsString[8]; dtostrf(Beaufort(meanSpeed), 1, 0, bsString); // Serial.print("Force: "); // Serial.println(bsString); client.publish("wind/speed/force", bsString); // Convert the Gust-Speed to a char array char gsString[8]; dtostrf(gustSpeed, 1, 0, gsString); // Serial.print("Gust: "); // Serial.println(gsString); client.publish("wind/gust/mph", gsString); // Convert the Gust-Speed-Force to a char array char bgString[8]; dtostrf(Beaufort(gustSpeed), 1, 0, bgString); // Serial.print("Gust Force: "); // Serial.println(bgString); client.publish("wind/gust/force", bgString); } void sendDirectionMessage(int Dir){ // Convert the Direction to a char array char dirString[8]; dtostrf(Dir, 1, 0, dirString); // Serial.print("Direction: "); // Serial.println(dirString); client.publish("wind/direction", dirString); } void sendDirectionMessageInst(int Dir){ // Convert the Direction to a char array char dirString[8]; dtostrf(Dir, 1, 0, dirString); // Serial.print("Direction: "); // Serial.println(dirString); client.publish("wind/direction/inst", dirString); } /* Debugging only void sendNumberMessage(int N){ // Convert the number to a char array char numString[8]; dtostrf(N, 1, 0, numString); Serial.print("Number: "); Serial.println(numString); client.publish("wind/number", numString); } void sendNumberMessage2(int N){ // Convert the number to a char array char numString[8]; dtostrf(N, 1, 0, numString); Serial.print("Number: "); Serial.println(numString); client.publish("wind/number2", numString); } */ void do3sJobs (){ byte instDir = readDirection(); sendDirectionMessageInst(instDir); // send instantaneous direction windSpeed += PulseCount; // Accumulate mean speed if (PulseCount > windGust) {windGust = PulseCount;}; // Get max speed for gust PulseCount = 0; ++bin[instDir]; // increment appropriate bin } void do1mJobs(){ // wind speed mean and gust ring arrays and report meanArray[ringIndex] = windSpeed; // put windSpeed into new array index gustArray[ringIndex] = windGust; // put windGust into new array index // windSpeed /=13; // /20 and *1.5 -- leave this for later meanSpeed = 0; gustSpeed = 0; windSpeed = 0; windGust = 0; for (int i = 0; i < 10; i++) { meanSpeed += meanArray[i]; // sum the windSpeeds if (gustArray[i] > gustSpeed){gustSpeed = gustArray[i];}; // find maximum gust speed } meanSpeed /=133; // the first sum was over 20 values and then the second over 10 values gustSpeed *= 1.5; // Speed count over 3s rather than 4.5s sendSpeedMessages(); // sendNumberMessage(ringIndex); debugging only ringIndex = (ringIndex+1)%10; // move ringIndex on to next location in the ring arrays } void do3mJobs(){ // wind direction calculations and report int sum[16]; int S=0,I=0,W=0; bin[16] = bin[0]; bin[17] = bin[1]; bin[18] = bin[2]; bin[19] = bin[3]; for (int i = 0; i < 16; i++) { sum[i] = bin[i] + bin[i+1] + bin[i+2] + bin[i+3] + bin[i+4]; // find the index with the highest sum and save sum and index if (sum[i] > S){S = sum[i]; I = i;}; // sendNumberMessage2(I); // send index for debugging } W = (bin[I+1] + 2 * bin[I+2] + 3 * bin[I+3] + 4 * bin[I+4]) * 45 / S; sendDirectionMessage((I * 45 + W)%720 /2); //Empty the bins ready for a new direction calculation for (int i = 0; i < 16; i++) {bin[i] = 0;}; } void loop() { if (!client.connected()) {reconnect();} client.loop(); // time the various periods long now = millis(); if(now - last3s > P3s) {do3sJobs(); last3s = now;} if(now - last1m > P1m) {do1mJobs(); last1m = now;} if(now - last3m > P3m) {do3mJobs(); last3m = now;} }
  21. I'm copying a post here as I don't know the best place for it.
  22. I'm getting a strange problem with the wind speed. Whether this is anything to do with MQTT or just the sketch in the wind ESP32 I don't know. Until today the speed calculations have been fine but now the mean speed keeps resetting then building up again to the correct value. These are enlargements of the mean speed history in the dashboard and the MQTT Explorer. I'm wondering if the stronger breeze today could be anything to do with it. Unfortunately, to upload a new sketch to the ESP32 in the wind client means taking the wind sensor mast and unit down and connecting the ESP32 to the Mint box USB. I seem to remember reading something about uploading a new Arduino sketch over WiFi but can't find it now.
  23. Oops re-read the description and those are not UV resistant so have cancelled order and ordered a couple of these instead. These ARE UV resistant. More expensive but better for the job. Ordered one and a spare so 2 off. Silicone O-Ring, 90mm OD, 85.2mm ID, 2.4mm Width, VMQ Seal Rings Gasket, Red
  24. Found the ideal rubber ring for sealing the dome. Have to buy 10 off when I only need 1 but no matter! Nitrile Rubber O-Rings 95mm OD 85mm ID 5mm Width, Metric Buna-N Sealing Gasket, Pack of 10
  25. Two possibilities for the screws that hold the ring to clamp the dome. Tapped holes in a solid lump of PLA or a flange with nuts and bolts. I think one problem with the old arrangement is that the wind could blow rain up the cone and under the dome. This flange would stop that. Also, since there is a possibility of needing to remove the dome more than once in the future, metal nuts are more suitable than threaded plastic!
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. By using this site, you agree to our Terms of Use.