Arduino Manager: Generate Raspberry Pi Pico C/C++ Code for an AC Power Monitor – Step-by-Step Example

by Fab64 in Circuits > Microcontrollers

279 Views, 5 Favorites, 0 Comments

Arduino Manager: Generate Raspberry Pi Pico C/C++ Code for an AC Power Monitor – Step-by-Step Example

Arduino Manager: Raspberry Pi Pico AC Power Monitor

This instructable provides an overview of the new features in Arduino Manager when using the Raspberry Pi Pico W to develop a simple Energy Monitor system. 

Specifically, Arduino Manager can now generate C/C++ code for the native Raspberry Pi C/C++ SDK, allowing users to program in C/C++ while taking full advantage of the available debugging features.

Arduino Manager, a powerful general purpose iOS iPadOS / watchOS / macOS App which allows to control any Arduino (or Arduino compatible) board by the means of about 40 different Widgets.

Some of the available Widgets are:

  1. Display Widget
  2. LED Widget
  3. Switch Widget
  4. Push Button Widget
  5. Knob Widget
  6. Slider Widget
  7. Alarm Widget
  8. Sound Alarm Widget
  9. Thermostat Widget
  10. Threshold Widget
  11. Text Widget
  12. and many more

Arduino Manager prioritizes your privacy, with no registration or cloud account required—only your Apple ID. However, you have the option to save your Widget Lists to iCloud, enabling seamless sharing across your devices.

For more information about Arduino Manager:

  1. Arduino Manager for iOS, Arduino Manager for macOS.
  2. Past Instructables:
  3. How to Control Arduino R4 WiFi From Your IPhone / Apple Watch / IPad / Mac
  4. Cheap IOT Device in Minutes and Without Writing Any Code Using Raspberry Pico Pi W
  5. Controlling ESP32 Running Micropython With Arduino Manager


The objectives of this Instructable are:

  1. Develop a simple device to measure AC voltage and current to calculate the apparent Power consumed by a load
  2. Manage a threshold to disconnect the load if the consumed power exceeds the threshold
  3. Manually rearm the device in case the load is disconnected
  4. Log consumption data over time
  5. Learn how to write the code for Raspberry Pi Pico W compatible with Arduino Manager keeping the coding as low as possible


Final Arduino Manager project result.


When the complexity of the Arduino code increases, such as when dealing with multiple analog and digital sensors to read, controlling numerous actuators, and implementing complex algorithms, the likelihood of making errors rises. Consequently, debugging the code becomes more challenging and the time and effort required to address these issues could significantly affect the progress of your project. For this reason Arduino Manager also provides (for an additional small fee):

  1. Code Generator: This add-on allows to generate the basic Arduino code for supporting the Widgets you need in your project.
  2. PIN Code Generator: Linking widgets to Arduino PINs, this add-on dramatically speeds up Arduino code development. In many cases you don't need to write a single line of code.

A nice additional feature is Voice Commands which allows to control most of the Arduino Manager Widgets by means of your voice (English only)!. See past Instructables form more.

Apple Watch is supported as well (with some limitations): you can control any Arduino board directly from your wrist, wherever you are in the world!

Arduino Manager for iOS/iPadOS is available here: App Store for $7.99 and includes the watchOS version. The macOS version is available here: App Store for $10.99 (please, note that not all the widgets are available on all the platforms).

More information, documentation, video tutorials, libraries and examples on Arduino Manager are available here:

Arduino Manager for iOS or here: Arduino Manager for macOS.

Supplies

  1. Arduino Manager
  2. Raspberry Pico Pi W
  3. SD Card reader (Optional)
  4. SCT013-30 current transformer (or any of the other in the family: SCT013-10, SCT13-20, etc.)

  5. ZMPT101B AC voltage sensor
  6. 1N5817 - Schottky diode
  7. 2 x 10K resistors 0.25W - 1%
  8. 470 resistor 0.25W - 5%
  9. Solid State Relay (out: 250V - 30A, in: 5V)
  10. AC Multimeter, better true RMS
  11. Oscilloscope (Optional)

Learn the Basic Theory

Screenshot 2024-11-04 at 6.38.20 PM.png

For DC voltage (V) and current (I) the power is defined as:

P = V * I

and it is measured in Watt.

For AC voltage and current everything is a bit more complex because voltage and current signals vary over time.

In this case, the RMS (Root Mean Square) values of the voltage and current are used to determine the power consumed by a load.

The RMS current value can be defined as the "value of the direct current that dissipates the same power in a resistor".

The simplified way to calculate the RMS value of a signal is:

RMS = SQRT [1/n * (x(t1)^2 + x(t2)^2 + .. + x(tn)^2)]

(See attached image)

For a sinusoidal signal, the RMS voltage can be approximated as:

Vrms = Vp * 0.7071.

Irms = Ip * 0.7071.

Keep the RMS formula in mind as it provides a practical way to calculate the Vrms and Irms values we'll need and use later.

Unfortunately, depending on the type of load (capacitive or inductive), voltage and current are not always in phase. This results in three different components of power: the real power, which depends on the resistive part of the load; the reactive power, which is influenced by the capacitive or inductive part; and the apparent power, which is a combination of the two. Technically, apparent power is a vector sum of the real power and reactive power vectors.

Since measuring the phase angle between voltage and current is challenging, we will calculate the apparent power only, by measuring voltage and current overt time and calculating the power as:

Pa = Vrms * Irms

and measured in Volt-Amperes (VA).

If you want to know more: AC Power.

Safety First!

The device we are building operates at low voltages, but part of it is powered by mains electricity.

Touching mains voltage can be fatal!

Regardless of your experience, the risk is even higher if you are inexperienced. Any actions you take are solely your responsibility. You have been warned.

Once again, if you are unsure of what you're doing, do not proceed. Seek help from someone with the necessary skills.

If you think you know what you're doing, think again.

At least, keep all mains voltage components (SCT013-30 and ZMPT101B) inside a plastic enclosure and never connect or manipulate them when connected to mains. This is the minimum safety measure required.

You are operating under your own exclusive responsibility, don't forget it!

How to Measure Voltage and Current

As we discussed earlier, we need to measure both voltage and current.

To measure the mains voltage, we will use a device (ZMPT101B) based on an electrical transformer. This passive component steps down the AC voltage to a lower level suitable for input into the Pico Pi’s ADC.

Since AC voltage fluctuates between positive and negative values, and the ADC only accepts only positive voltages, the device also shifts the voltage values upwards.

The current measurement is based on the principle that each AC current creates a varying magnetic field which can be captured by a solenoid to generate a proportional but lower current across it. That current flowing through a resistor generates a voltage that can be measured by the Pico PI's ADC.

The chosen device (SCT013-30) already has an internal resistor. Also the current has positive and negative values (so that the generated voltage generated at the internal resistor) and we have to shift the current values upwards externally.

To calculate the RMS value, the voltage is measured at regular intervals to obtain a series of samples. These samples are then applied to the RMS formula, yielding the effective RMS value of the voltage.

The sampling frequency must be at least twice the frequency of the voltage signal, according to the Nyquist Theorem.

Build the Power Monitor Device

PowerMonitor_01_bb.png
PowerMonitor_01_schem.png

To assemble the Power Monitor Device, please refer to the included breadboard mounting plan and schematic. The setup is straightforward and can be completed in just a few minutes. You can use either a breadboard or stripboard.

Regardless of your chosen method, it is essential for safety that all components in contact with mains voltage are enclosed in a plastic container to prevent accidental contact with high voltage, which could be fatal.

We have already discussed the methods for measuring voltage and current. Here are some additional key points to consider:

  1. Due to the presence of AC voltages, the output of the current sensor fluctuates between positive and negative values. Since the Pico's ADC can only accept positive voltages, resistors R2 and R3 are used to create a constant voltage of approximately 1.65V (3.3V / 2). This shifting of the current sensor's output allows it to remain within the ADC's acceptable range, and the constant offset can be removed later in software.
  2. The Pico is powered by an external 5V DC supply. The Schottky diode (D1 - 1N5817) enables the Pico to connect to your computer via USB without causing a power conflict. For more information, refer to section 4.5 of the Raspberry Pi Pico datasheet.
  3. A solid-state relay is used to connect and disconnect the load to the mains. Additionally, if the power consumption exceeds a predefined threshold, the device can disconnect the load through the relay. The transistor (Q1 - BC237) drives the relay, ensuring that the Pico's pin remains protected from overload.

Please note that the power supply is connected to the mains before the current sensor to ensure that power measurements are not influenced by the consumption of the power supply itself.

We are now ready to begin the programming phase of the project.

Check ICloud Login

If you are using an iOS device (iPhone or iPad) to run Arduino Manager, you must be logged into iCloud to access the code generated by the app.

If you're not logged in yet, now is a good time to do so.

Additionally, make sure the 'Sync this iPhone' option is enabled, which can be found here:

Settings ⇾ iCloud ⇾ Drive

Arduino Manager Widget List Preparation

Screenshot 2024-10-27 at 6.16.34 PM.png
Screenshot 2024-10-27 at 6.17.55 PM.png
Screenshot 2024-11-04 at 6.52.58 PM.png
iPhone.png

To keep this Instructable concise, we’ll assume you can create the widget list yourself. For additional guidance, you can refer to the previously mentioned Instructable or consult the Arduino Manager documentation via the provided links.

Attached is the pre-configured Widget List that you can use without configuring a new one.

To load it into Arduino Manager, follow these steps based on your platform:

macOS:

  1. Download the file: Energy Monitor.amwl.txt
  2. Rename it to: Monitor.amwl
  3. Right-click the file and open it with Arduino Manager.
  4. To sync the Energy Monitor Widget List across all your Apple devices, the Widget Lists panel, move the Energy Monitor to iCloud using the app, and it will be accessible from anywhere."

Windows - iPhone/iPad:

  1. Download the file: Energy Monitor.amwl.txt
  2. Rename it to: Monitor.amwl
  3. Copy the file to your iCloud folder.
  4. Open the Files app on your iPhone/iPad.
  5. Locate the file in the 'Recents' tab.
  6. Long press on the file and select 'Download Now.'
  7. Once downloaded, tap the file to open it in Arduino Manager.

The Widget List is divided into two pages: the first displays the measured voltage, current and power, shows the power trend over time, and allows manual rearming of the load if needed.

The second page is for device setup and calibration.


Generate the C/C++ Pico Code

Screenshot 2024-10-25 at 4.41.15 PM.png
Screenshot 2024-10-27 at 6.19.36 PM.png
Screenshot 2024-10-27 at 6.19.08 PM.png
Screenshot 2024-10-25 at 9.44.52 AM.png
Screenshot 2024-10-27 at 6.20.12 PM.png
Screenshot 2024-10-27 at 6.26.32 PM.png

This step allows you to generate the code for Pico W in a matter of seconds. There are two major steps:

1) General Project Configuration: Main project information and IP connection information

2) Pins Configuration: Which PINs are used for reading voltage, current and control the relay

General Project Configuration

  1. From Widget Lists select the Energy Monitor one
  2. Click on Code Generator
  3. Click on New to create a new Project and enter the project's name: Energy Monitor Instructable
  4. Select Raspberry Pico W
  5. Select the connection Energy Monitor (IP field and Port field are automatically updated). In case you need a different IP or Port, update the Connection first or enter them manually.
  6. In the Netmask field enter a value compatible with your network (e.g. 255.255.255.0).
  7. In the Gateway field enter a value compatible with your network (e.g. 192.168.1.1).
  8. In the SSID and Password fields enter values compatible with your network.
  9. Enable both the Callbacks. This is not strictly required.

Widget Pins Configuration

  1. Click Widget Pins
  2. Select the Display - Voltage row
  3. Select Pin: 26
  4. Read Value Every: 450 ms
  5. Input Preprocess Function: on
  6. Select Display - Current row
  7. Select Pin: 27
  8. Read Value Every: 450 ms
  9. Input Preprocess Function: on
  10. Select the Secure Push Button - Enable Load
  11. Select Pin: 15 (GPIO15, where the Relay is connected)
  12. Value at Power On: High (relay enabled, load powered)
  13. Triggered Value: High (to rearm the load)
  14. Select the Led - Load
  15. Select Pin: 15 (GPIO15) so that the Led Widget light up when the load is powered
  16. Click Generate to generate the code for you.

Logged Data Graphs

  1. Click Logged Data Graphs
  2. Select Trends
  3. Enter:
  4. Label 1: Voltage
  5. Label 2: Current
  6. Label 3: Power
  7. Sampling Period: 60 [s]
  8. Max Number of Samples: 500
  9. Preprocess Function: on

Click Generate to generate the code.

The Code Generator generates the code to performs the following tasks:

  1. Read PIN 26 every 450 ms and call the preprocess_display_Voltage function to measure the RMS voltage. Store the resulting value in the variable voltage_RMS and periodically send this value to the Arduino Manager to keep the Display Widget updated. The preprocess_display_Voltage function is designed to calculate the RMS value of the voltage rather than just the instantaneous value
  2. Read PIN 27 every 450 ms and call the preprocess_display_Current function to measure the RMS current. Store the resulting value in the variable current_RMS and periodically send this value to the Arduino Manager to keep the Display Widget updated. The preprocess_display_Current function is designed to calculate the RMS value of the current instead of merely capturing its instantaneous value
  3. Activate PIN 15 when the Enable Load button is pressed in the Arduino Manager
  4. Send the status of PIN 15 to the LED Widget to indicate whether it is enabled or disabled

Configuring the C/C++ Project in Visual Studio Code

In this section, we assume your development environment is already set up and functioning. If not, please refer to the official documentation for setup instructions: Getting started with Raspberry Pi Pico.

To get started with the project generated by Arduino Manager, follow these steps:

  1. Open Visual Studio Code on your macOS or PC
  2. Click on Raspberry Pico Extension and select: Import Project
  3. Select location: iCloud Drive ⇾ Arduino Manager ⇾ Energy_Monitor_Instructablelib

  4. Select your debugger
  5. Click import
  6. Create a folder called: lib
  7. Right click on the lib folder and select Open in Integrated Terminal
  8. Enter the following commands
git clone --recurse-submodules https://github.com/ArduinoManager/AM_SDK_PicoWiFi.git
git clone --single-branch --recurse-submodules https://github.com/carlk3/no-OS-FatFS-SD-SDIO-SPI-RPi-Pico.git
cd no-OS-FatFS-SD-SDIO-SPI-RPi-Pico
git switch --detach tags/v3.5.1
  1. Download Measurement.h and copy it to the project folder
  2. Download Configuration.h and copy it to the project folder
  3. Click on Raspberry Pi Pico Extension on the left bar and select Configure CMake
  4. Click Compile

If the project compiles without any error, the setup is complete.

The Configuration class enables storing configuration data in the Pico's flash memory, preserving it across power cycles.

The Measurement class handles reading the output from the two measurement devices, calculating RMS values, and supporting calibration procedures.

Quick Overview of Measurement Class

The Measurement class manages voltage and current measurements, calculates RMS values, and includes additional functions to facilitate initial calibration of the voltage sensor.

Here's an overview of each function's purpose:

  1. voltage (current): captures instantaneous voltage (or current) values. To minimize noise, oversampling is applied, with the three lowest and highest samples discarded for greater accuracy.
  2. mean_voltage (mean_current): computes the average value of the voltage (or current) used to precisely determine the offset values for both
  3. voltage_rms (current_rms): calculates the RMS value of voltage (or current) based on the formula outlined in Step 1

Preparing Configuration and Measurement Classes

Before deep diving the calibration procedure, we have to integrate the two additional class provided.

Open the Measurement.h file and set the sampling frequency according to your mains.

For 50Hz mains:

#define sleep sleep_us_50hz

For 60Hz mains:

#define sleep sleep_us_60hz

Then open the Energy_Monitor_Instructable.cpp and locate the following lines:

/* Start your code (defines) */
/* End your code */

Adding your code between these two tags allows you to preserve it across multiple code generations. All other tags in the code function in the same way.

Change them as follows:

/* Start your code (defines) */
#include "Measurement.h"
#include "Configuration.h"
Measurement measurement(PIN_VOLTAGE, PIN_CURRENT);
Configuration configuration;
/* Start your code (defines) */

Locate the lines

/* Start your code (setup) */
/* End your code */


Change them as follows:

/* Start your code (setup) */
v_dc = configuration.getVdc();
i_dc = configuration.getIdc();
max_Power = configuration.getMaxPower();
measurement.setVdc(v_dc);
measurement.setIdc(i_dc);
/* End your code */


The variables v_dc and i_dc represent the voltage and current offsets to be accounted for in RMS calculations and the max power that the load can consume.

These values are loaded each time the Pico powers up through the Configuration class, which stores and retrieves them from the Pico's Flash memory.

Find the following lines:

/* Start your code (pushButtonVoltageOffsetCallback) */
/* End your code */

and replace them with the following:

/* Start your code (pushButtonVoltageOffsetCallback) */
if (pushed) {
v_dc = measurement.mean_voltage();
configuration.setVdc(v_dc);
measurement.setVdc(v_dc);
}
/* End your code */


The push_button_VoltageOffset_callback function is triggered each time the Voltage Offset button is pressed in Arduino Manager to initiate measurement of the voltage sensor's output.

With the mains disconnected, this voltage should ideally be half of the 3.3V power supply. However, to improve accuracy, the actual value is measured and stored in the configuration data in flash memory.

Change the push_button_CurrentOffset_callback in a similar way:

/* Start your code (pushButtonCurrentOffsetCallback) */
if (pushed) {
i_dc = measurement.mean_current();
configuration.setIdc(i_dc);
measurement.setIdc(i_dc);
}
/* End your code */

Compile the program and run it.

Arduino Manager Connection Configuration

Screenshot 2024-10-27 at 6.29.20 PM.png

In Arduino Manager, click Connections to view the available connections.

If you downloaded the Widget List in Step 6, the Energy Monitor Instructable connection should already be available. Edit it to ensure the IP address and port match exactly with the ones you entered when generating the project in Step 7.

If the connection is not available, create a new one using the same values from Step 7.

If the connection parameters don't match the ones you entered when generating the project in Step 7, modify the connection accordingly.

Then click Widgets and from the page 1 setup button (wrench icon) select it. Switch to page 2 and repeat the process.

Connection to Raspberry Pico W and First Check

With mains still disconnected, click the connection button at the bottom of the Widgets page, and the blue LED should light up to confirm that Arduino Manager has successfully connected to the Pico W.

Both Current Offset and Voltage Offset Display Widgets will display 1.65, which is the default offset value stored into the configuration.

Push Voltage Offset button and immediately afterward the Voltage Offset should display the actual offset value at the voltage sensor's output.

Push Current Offset button and immediately afterward the Current Offset should display the actual offset value at the current sensor's output.

Voltage Calibration

SDS00002.BMP
SDS00001.BMP
Screenshot 2024-10-27 at 4.33.05 PM.png

We have measured and stored the voltage offset at the ZMPT101B's output, but the calibration procedure is not completed yet.

The ZMPT101B device features an internal operational amplifier that amplifies the small signal from the transformer, helping to reduce noise in the Pico's ADC.

However the amplifier can saturate —meaning it may amplify the signal too much— resulting in clipped output that affects the RMS calculation. For that reason the ZMPT101B is equipped with a trimmer to fine-tune the gain and prevent saturation.

If you have an oscilloscope, fine-tuning the gain is quite easy:

  1. Connect the mains
  2. Power up the device
  3. Connect the oscilloscope at the ZMPT101B using AC coupling
  4. Rotate the trimmer until the output is a pure sinusoidal signal

The first photo shows an example of a saturated output, where the signal is distorted. The second photo displays the same signal after the gain has been properly adjusted.

If you don't have an oscilloscope, you have to modify the code first than tune the trimmer.

Find this Start your code (defines) section and change as follows:

/* Start your code (defines) */
#include "Measurement.h"
#include "Configuration.h"
Measurement measurement(PIN_VOLTAGE, PIN_CURRENT);
Configuration configuration;
bool voltage_calibration = false;
/* Start your code (defines) */


Find the function switchCalibrateVoltageCallback and change its body as follows:

/* Start your code (switchCalibrateVoltageCallback) */
voltage_calibration = on;
/* End your code */


This function is triggered when the Calibrate Voltage switch in Arduino Manager is turned on.

Find the doWork function and change it as follows:

/* Start your code (doWork) */
if (voltage_calibration) {
voltage_calibration_data data = measurement.voltage_calibration(v_dc);
value = data.value;
delta = data.delta;
sleep_ms(450);
}
/* End your code */


Compile, run the code and connect Arduino Manager to Pico. Operate the trigger in order to get the maximum possible Value and the minimum possible absolute value of Delta.

Turn off the Calibrate Voltage.

Finally, we can begin measuring the RMS values through the Measurement class. To do this, we need to update the preprocess_my_voltage and preprocess_my_current functions:

/* Start your code (preprocessDisplayVoltage) */
ret = measurement.voltage_rms();
/* End your code */


/* Start your code (preprocessDisplayCurrent) */
ret = measurement.current_rms();
/* End your code */


and change the doWork custom code as follows:


/* Start your code (doWork) */
if (voltage_calibration) {
voltage_calibration_data data = measurement.voltage_calibration(v_dc);
value = data.value;
delta = data.delta;
sleep_ms(450);
}
power = voltage_RMS * current_RMS;
/* End your code */


Next, we need to properly scale the value read by the ADC to match the actual mains voltage, following these steps:

Be careful, mains voltage can be lethal.

  1. Disconnect the mains
  2. Connect the AC multimeter to the ZMPT101B input to measure the actual mains voltage (Vac).
  3. Reconnect the mains
  4. Read the value on the Value Display in Arduino Manager (value)

The scale factor is the formula:

ZMPT101B_SCALE = Vac / value

For example if the multimeter displays 234V and the Value displays 0.189V, the scale factor is:

ZMPT101B_SCALE = 234 / 0.271 = 863.47

Open the file Measurement.h and update the following line accordingly:

#define ZMPT101B_SCALE 863.47

Re-run the program and now the Value display should be very close to the value measured by the multimeter.

Current Calibration

The scaling factor for the SCT013-30 sensor, as specified in its documentation, is 30 A/V.

Open the file Measurement.h and update the following line accordingly:

#define SCT_013_30_SCALE 30.0 // Scale to convert the SCT-013-30 output to actual current

If you are using a different sensor with a different rated output, adjust the scale factor accordingly.

Due to noise captured by the sensor—especially if the device is built on a breadboard—the Current Display may show a value even when the power is not connected. If you encounter this issue, please adjust the following lines according to your measured levels.

// Any RMS value under 0.007 is assumed 0
if (current_rms < 0.007) {
current_rms = 0.0;
}

Complete the Code

Last remaining step is check that the power doesn't exceed the maximum value set via the Threshold Widget in Arduino Manager.

Change the doWork custom code as follows:

/* Start your code (doWork) */
if (voltage_calibration) {
voltage_calibration_data data = measurement.voltage_calibration(v_dc);
value = data.value;
delta = data.delta;
sleep_ms(450);
}
power = voltage_RMS * current_RMS;
if (power > max_Power) {
gpio_put(PIN_LOAD, false);
}
/* End your code */


The function threshold_MaxPower_callback is triggered when the threshold is set in Arduino Manager, change the code as follows to save any new value:

/* Start your code (thresholdMaxPowerCallback) */
configuration.setMaxPower(max_Power);
/* End your code */


Compile and run the code.

In Arduino Manager use the plus and minus button of the Threshold Widget to set the maximum power that the load can consume.

If the load temporarily exceeds this limit, it will automatically disconnect. To restore power, press the Enable Load button.

Logging Power Consumption

To display the trends of voltage RMS, current RMS, and power over time using the Trends Logged Data Graph Widget, modify the functions preprocess_trends_voltage, preprocess_trends_current, and preprocess_trends_power. These functions are called periodically before data is stored on the SD card, allowing the injection of RMS values and calculated power.

/* Start your code (preprocess_trends_voltage) */
ret = voltage_RMS;
/* End your code */


/* Start your code (preprocess_trends_current) */
ret = current_RMS * 1000;
/* End your code */

Scale the current by multiplying it by 1000 if its values are significantly smaller than the voltage values; otherwise, the current graph may be difficult to read.

/* Start your code (preprocess_trends_power) */
ret = power;
/* End your code */

Compile and run the program again, after after a few minutes, you can view the graph by pressing the reload button on the Trends Logged Data Graph Widget.


Wrap Up

Using Arduino Manager, we’ve created an efficient interface to monitor the power consumption of a load and control it remotely in a simple and effective way.

The majority of the code was generated automatically, allowing us to focus on the core aspects of the project (e.g. RMS values calculation).

C++ project setup, communication details, message processing, and other intricate elements are handled by Arduino Manager’s code generator, streamlining development.

The recent update to Arduino Manager, which now generates native C/C++ code, combined with the power of the Raspberry Pi Pico W, enables the creation of complex projects while allowing for advanced debugging with a real debugger—an improvement over relying on Serial.println() as in the traditional Arduino IDE.