I posted earlier about a couple of SAMD21 mini modules that I'm using SAMD21 Mini Modules .
Last month Seeed Studio released an Expansion board for their XIAO module https://www.seeedstudio.com/Seeeduino-XIAO-Expansion-board-p-4746.html .
I've been using their Grove shield for the XIAO and it's handy for prototyping sensor programs and it also has battery management for portability https://www.seeedstudio.com/Grove-Shield-for-Seeeduino-XIAO-p-4621.html .
I was able to get a couple of the Expansion boards at the special introductory price of $9.90. The Expansion boards offer quite a bit of functionality as shown in the spec:
The RTC and microSD card will make it useful for prototype datalogging and it also includes a LiPo battery interface.
One feature that they added are pogo (spring) pins to bring the SWD (software debugger) signals from pads on the bottom of the Xiao board to a header on the Expansion board.
It's a nice feature that I might use but I realized that I won't be able to use this board with the Adafruit QT Py unless I remove those pins because the QT Py has 5V and GND pads there - see below. Since I have two boards I'll probably modify one to use with the QT Py.
The first thing I decided to try was the RTC.
Here is the code: (After setting the time I commented out that part of the code)
Xiao_OLED_RTC.ino
#include <Arduino.h>
#include <U8x8lib.h>
#include <PCF8563.h>
PCF8563 pcf;
#include <Wire.h>
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
//U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // OLEDs without Reset of the Display
void setup() {
Serial.begin(115200);
u8x8.begin();
u8x8.setFlipMode(0);
Wire.begin();
pcf.init();//initialize the clock
// Comment out after setting the time
// pcf.stopClock();//stop the clock
// pcf.setYear(20);//set year
// pcf.setMonth(12);//set month
// pcf.setDay(19);//set dat
// pcf.setHour(9);//set hour
// pcf.setMinut(41);//set minute
// pcf.setSecond(0);//set second
// pcf.startClock();//start the clock
}
void loop() {
Time nowTime = pcf.getTime();//get current time
u8x8.setFont(u8x8_font_chroma48medium8_r); // choose a suitable font
u8x8.setCursor(0, 0);
// u8x8.print(nowTime.day);
u8x8.print(nowTime.month);
u8x8.print("/");
// u8x8.print(nowTime.month);
u8x8.print(nowTime.day);
u8x8.print("/");
u8x8.print("20");
u8x8.print(nowTime.year);
u8x8.setCursor(0, 1);
u8x8.print(nowTime.hour);
u8x8.print(":");
u8x8.print(nowTime.minute);
u8x8.print(":");
u8x8.println(nowTime.second);
delay(1000);
}
After trying the code out, I powered down the board and to my dismay I discovered that the RTC did not retain the time information. A bit of quick probing with a DMM and I found that the GND pad under the battery holder that is the negative terminal contact was covered with flux. I guess it's hard to clean because I had to use tweezers and tissue soaked with alcohol to get it clean (a Q-Tip or brush won't fit). Now it all works but I had to reprogram the time.
Next I decided to try out plotting a sensor on the OLED. I had used the U8x8 library for the RTC display but need to switch to the AdaFruit SSD1306 and GFX libraries for graphics. I've been using a Grove DHT11 Temperature and Humidity sensor for some other experiments so I decided to try that out.
I found some charting code by Kris Kasprzak - FREE Functions to draw graphs on OLED displays https://www.youtube.com/watch?v=13PFOwcK3-I , so I appropriated the line chart from that. The code does not do continuous plotting, so I'll need to modify that later.
Xiao_Temp_Plot.ino
/*
This program plots DHT11 Temperature Data
using Xiao Expansion Board
*/
#include "DHT.h"
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define DHTPIN 0 // what pin we're connected to
#define DHTTYPE DHT11 // DHT 11
DHT dht(DHTPIN, DHTTYPE);
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
// create what ever variables you need
double x, y;
// these are a required variables for the graphing functions
bool Redraw1 = true;
bool Redraw2 = true;
bool Redraw3 = true;
bool Redraw4 = true;
double ox , oy ;
void setup() {
Serial.begin(115200);
dht.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.display();
}
unsigned long OldTime;
unsigned long counter;
void loop(void) {
double temp, humid;
temp = dht.readTemperature()*1.8 + 32;
humid = dht.readHumidity();
Serial.print("Temperature: ");
Serial.print(temp);
Serial.println(" *C");
DrawCGraph(display, x++, temp, 30, 50, 80, 40, 0, 100, 25, 60, 80, 10, 0, "Temperature F", Redraw4);
if (x > 100) {
while (1) {}
}
delay(1000);
}
/*
&display to pass the display object, mainly used if multiple displays are connected to the MCU
x = x data point
y = y datapoint
gx = x graph location (lower left)
gy = y graph location (lower left)
w = width of graph
h = height of graph
xlo = lower bound of x axis
xhi = upper bound of x asis
xinc = division of x axis (distance not count)
ylo = lower bound of y axis
yhi = upper bound of y asis
yinc = division of y axis (distance not count)
title = title of graph
&redraw = flag to redraw graph on fist call only
*/
void DrawCGraph(Adafruit_SSD1306 &d, double x, double y, double gx, double gy, double w, double h, double xlo, double xhi, double xinc, double ylo, double yhi, double yinc, double dig, String title, boolean &Redraw) {
double i;
double temp;
int rot, newrot;
if (Redraw == true) {
Redraw = false;
d.setTextSize(1);
d.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
d.setCursor(35, 4);
d.println(title);
// d.fillRect(0, 0, 127 , 16, SSD1306_WHITE);
// d.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
// d.setTextSize(1);
// d.setCursor(2, 4);
// d.println(title);
ox = (x - xlo) * ( w) / (xhi - xlo) + gx;
oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
// draw y scale
d.setTextSize(1);
d.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
for ( i = ylo; i <= yhi; i += yinc) {
// compute the transform
// note my transform funcition is the same as the map function, except the map uses long and we need doubles
temp = (i - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
if (i == ylo) {
d.drawFastHLine(gx - 3, temp, w + 3, SSD1306_WHITE);
}
else {
d.drawFastHLine(gx - 3, temp, 3, SSD1306_WHITE);
}
d.setCursor(gx - 27, temp - 3);
d.println(i, dig);
}
// draw x scale
for (i = xlo; i <= xhi; i += xinc) {
// compute the transform
d.setTextSize(1);
d.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
temp = (i - xlo) * ( w) / (xhi - xlo) + gx;
if (i == 0) {
d.drawFastVLine(temp, gy - h, h + 3, SSD1306_WHITE);
}
else {
d.drawFastVLine(temp, gy, 3, SSD1306_WHITE);
}
d.setCursor(temp, gy + 6);
d.println(i, dig);
}
}
// graph drawn now plot the data
// the entire plotting code are these few lines...
x = (x - xlo) * ( w) / (xhi - xlo) + gx;
y = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
d.drawLine(ox, oy, x, y, SSD1306_WHITE);
d.drawLine(ox, oy - 1, x, y - 1, SSD1306_WHITE);
ox = x;
oy = y;
// up until now print sends data to a buffer NOT the screen
// this call sends the data to the screen
d.display();
}
Probably need to do some real work (I hear the wife vacuuming
). I'll have to try datalogging to the SD card later.






Top Comments