element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
    About the element14 Community
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      •  Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
On the Line
  • Challenges & Projects
  • Design Challenges
  • On the Line
  • More
  • Cancel
On the Line
Forum SolarSense - Part 7 - Reading the Sky - UV Sensor Interface on STM32
  • News
  • Projects
  • Forum
  • DC
  • Leaderboard
  • Files
  • Members
  • More
  • Cancel
  • New
Join On the Line to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • Replies 5 replies
  • Subscribers 35 subscribers
  • Views 138 views
  • Users 0 members are here
  • design challenge
  • On The Line
Related

SolarSense - Part 7 - Reading the Sky - UV Sensor Interface on STM32

arvindsa
arvindsa 24 days ago

Recap:

I'm building a smart solar monitoring system that uses three panels with a clean reference to eliminate weather effects and directly measure dust-induced losses in real time. One panel stays pristine as a baseline, and comparing the two under identical sky conditions gives a performance ratio that reveals soiling immediately. The goal is to use environmental sensors and edge AI to predict exactly when cleaning is needed, before efficiency drops enough to impact revenue. This beats fixed-schedule cleaning or waiting for output to degrade.Also this is complementary to my Master's thesis of a minute Shape memory Alloy based solar panel cleaning robot

Previous posts:

  • SolarSense - Part 1 - Introduction, The POC Built and The Plan
  • SolarSense - Part 2 - Can Arduino CAN?
  • SolarSense - Part 3 - PCB Schematics Walkthrough
  • SolarSense - Part 4 - CAN Protocol Deep Dive and Implementation
  • SolarSense - Part 5 - Making an Live Dashboard using Lab View
  • SolarSense - Part 6 - Reading the Heat at K Type Thermocouple using MAX31855.

Why UV?

The obvious answer you might think is "because UV degrades solar panels like so many other things." And yes, that is absolutely true. UV radiation is the primary driver of photovoltaic cell degradation over years of operation. The casing yellows, the anti-reflection coating breaks down, Tracking cumulative UV dose over time gives a solid predictor for long-term efficiency loss that has nothing to do with dust.

But for this project, That would not be the answer, UV degradation is established fact and there is no point in doing any research on it. But what is interesting is that  Solar irradiance (energy per unit area) and UV index do not move in together. Clouds scatter and absorb visible light far more aggressively than they block UV — there are days where the sky looks completely overcast and the UV index is still punishing. The panels see almost no visible light but a significant UV dose. If my model only tracks panel output and misses UV, it cannot distinguish "sky is genuinely dark" from "sky is bright but the panel surface is blocked." UV gives the model context about what the actual sky condition is, independent of what the panels are producing.

The key insight: UV index is a proxy for the radiative environment that survives cloud cover in a way that visible irradiance does not. That independence is exactly what makes it useful as a model input. Now, I have to emphasize that the UV is not an authoritative indicator for passing clouds etc but it will be helpful.

What the GUVA Sensor Actually Does

The GUVA-S12SD is a GaN-based Schottky-type photodiode that is sensitive from roughly 240 nm to 370 nm. That range covers UV-B (280–315 nm) and most of UV-A, but the response peaks around 360 nm and falls to near zero before 400 nm — so visible light is well and truly rejected. The sensor is genuinely seeing UV, not just acting as a general light sensor with a blue filter.

image

What the chip itself produces is a current proportional to incident UV intensity. The datasheet specifies a responsivity of 0.14 A/W at 300 nm and a photocurrent of 26 nA per UV index unit under sunlight conditions. On the Adafruit breakout module, this current feeds into an op-amp circuit that amplifies it to a usable voltage level. Adafruit’s documentation states the conversion as: V_out = 4.3 × I_photodiode_in_µA

Condition Approximate V_out UV Index
Dark / indoors 0.05 – 0.15 V 0 – 1
Overcast outdoor 0.15 – 0.40 V 1 – 4
Hazy sun 0.40 – 0.80 V 4 – 8
Clear noon Kerala summer 0.90 – 1.40 V 9 – 14

My 0.3 V reading at test time is UV Index 3  exactly right for indoors near a window. The formula to compute UV index from the output voltage is simply dividing by 0.1 V, or in firmware:

/* UV index in tenths from GUVA output voltage.
   Per Adafruit: UV index = V_out / 0.1 V  →  tenths = uv_mv / 10 */
uint32_t uv_idx10 = uv_mv / 10U;

The Code

There are two pieces of setup required before any ADC conversion can be usable on the STM32L4. The first is the calibration call unlike older STM32 families, the L4’s ADC has an internal calibration routine that must be run once at startup before the first conversion. It writes offset correction values to the ADC’s internal registers and takes only a few microseconds. Without it, readings come out inaccurate. This goes right after MX_ADC1_Init():

HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);

After that, reading the UV channel each telemetry tick is straightforward. The ADC is in scan mode with four ranks, which means all four channels are sequenced on every trigger — you cannot read just rank 1 in isolation. You have to drain all four values or the next conversion starts out of step.

The Conversion Rank in CubeMX

image

/* UV sensor (GUVA analog) on ADC1 rank 1 (ADC_CHANNEL_5 / PA0).
   Scan group has 4 ranks; all must be drained on every conversion. */
if (o < (int)sizeof(tlm) - 16)
{
    uint32_t uv_raw = 0;
    if (HAL_ADC_Start(&hadc1) == HAL_OK)
    {
        if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
            uv_raw = HAL_ADC_GetValue(&hadc1);
        /* Drain ranks 2-4 (HX94C RH, HX94C TEMP, RAIN AO) */
        for (int r = 1; r < 4; r++)
        {
            if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
                (void)HAL_ADC_GetValue(&hadc1);
        }
        HAL_ADC_Stop(&hadc1);
    }
    uint32_t uv_mv = uv_raw * 3300U / 4095U;
    o += snprintf(tlm + o, sizeof(tlm) - o, " uv_mv=%lu", (unsigned long)uv_mv);
}

The Readings

Just Like in the measurement of the temperature at the thermocouple, I do not have a calibrated UV source or measurement system. So I am going to just see if the multi-meter reading of signal output is same as what STM32 picks up. 

image

image

Final Notes

One line of calibration code. That is the whole lesson here. HAL_ADCEx_Calibration_Start on the STM32L4 is not optional.

The UV sensor is live and reading sensibly. Next I want to run it through a full day outdoors and plot the curve rising from low values before sunrise, peaking around local solar noon, dropping back. If the curve shape looks right and correlates with what I would expect for the season and latitude, I will be satisfied that the sensor is working correctly.

After that, the environmental sensors  BMP280 and the HX94C are next in the queue. The ADC scan group already has the HX94C analog channels wired up, it is just waiting for code similar to what I did here. The sensing stack is getting close to complete. I am yet to solder the BMP280. I am hesitant because deep down in my heart, It feels like pressure is not going to be an useful parameter.

 

  • Sign in to reply
  • Cancel
  • saramic
    saramic 23 days ago

    Nice, I did actually get a few extra sensors but due to some delayed shipping and being flat out at home may not get them hooked up - again left too much to crunch time

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • arvindsa
    arvindsa 23 days ago in reply to saramic

    Argh. I hate when late shipping disrupts our schedule. 

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • Dipeshkachhi
    Dipeshkachhi 23 days ago

    Great progress on the Solarsense project! Interfacing a UV sensor is a perfect next step for a solar monitoring system.

    Which UV sensor are you using (e.g., GUVA‑S12SD, VEML6070, or something else)? Also, are you using the STM32's built‑in ADC or an I²C interface for reading it?

    I'm curious about how you're handling calibration – did you use a reference source, or are you relying on the sensor's datasheet curves? Ambient temperature compensation can be tricky with UV sensors.

    Looking forward to the next part – keep up the good work!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • arvindsa
    arvindsa 23 days ago in reply to Dipeshkachhi

    I have to be blunt here. The answer to all your questions are in the forum post. I would have understood if you missed a paragraph or two, But Honestly, this seems that you used AI to make a comment based on the heading. 

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • DAB
    DAB 22 days ago

    Nice project.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2026 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube