I'll try to share with community some kind of my test-code/sketches that I collected/wrote during the work on Z-Uno project. It could be helpful for some cases. In most cases I have not time to make a full-size tutorial or a blog posts. So, it will be a brief format of the forum posts. The main target of them is to make the most non evident features of Z-Uno available to the large number of users.
It's a first take.
The first thing I like to talk about is dynamic channels.
It was available from version 2.1.0. There are two publicated examples available that use this approach:
1. http://z-uno.z-wave.me/examples/z-uno-as-a-modem/
2. http://z-uno.z-wave.me/examples/multipl ... e-sensors/
The main advantage is that you can use the same code for a lot of channels instead of making getter/setter for every channel.
Lets look to my code that use this approach to create a multichannel binary switch on all pins of Z-Uno. Here is the code
Code: Select all
/*
This sketch provide a method to control up to 21
switch. You have to configure the number or channels you
want via parameter #64. Default value is 4.
You can use this to control open drain controlling device.
For this purpose you have to setup parameter #65 to 0.
It switches normal/inverse logic.
0 = inverse (open drain) logic,
1 = normal logic
This sketch uses dynamic approach of channel definition
to decrease code space and demonstrate how to use it.
See setup() & zunoCallback() functions for details.
(c) Z-Wave>ME 2017
*/
#define DEFAULT_NUMBER_OF_CHANNELS 4
#define DEFAULT_CHANNEL_LOGIC 1
byte number_of_channels = DEFAULT_NUMBER_OF_CHANNELS; // Default
byte channel_logic = DEFAULT_CHANNEL_LOGIC;
dword tmp;
// pin mapping
byte pin_mapping[]={0, // ZUNO GPIO #0
1, // ZUNO GPIO #1
2, // ZUNO GPIO #2
// -- WE SKIP UART0, LEAVE IT FOR DEBUG --
// UNCOMMENT IF NEEDED
// 24, // TX0
// 25, // RX0
// --------------------
3, // ZUNO A0
4, // ZUNO A1
5, // ZUNO A2
6, // ZUNO A3
7, // ZUNO GPIO #7
8, // ZUNO GPIO #8
9, // ZUNO GPIO #9
10,// ZUNO GPIO #10
11,// ZUNO GPIO #11
12,// ZUNO GPIO #12
13,// ZUNO PW1
14,// ZUNO PW2
15,// ZUNO PW3
16,// ZUNO PW4
17,// ZUNO GPIO 17
// -- WE SKIP INT1, IT ALWAY PULLED UP --
// IF YOU NEED NC PIN - YOU CAN UNCOMMENT IT
// 18, // INT1
// --------------------
19,
20,
21,
22,
// -- WE SKIP BTN
// IF YOU NEED NC PIN - YOU CAN UNCOMMENT IT
// 23, // BTN
// --------------------
};
byte pin_states[sizeof(pin_mapping)];
// the setup function runs once, when you press reset or power the board
void setup() {
byte i;
// Loading configuration data...
zunoLoadCFGParam(64,&tmp); // Here we can use dword, but byte is cheaper
number_of_channels = tmp;
zunoLoadCFGParam(65,&tmp); // Here we can use dword, but byte is cheaper
channel_logic = tmp;
// Check if value of param is valid
if(number_of_channels > sizeof(pin_mapping) || number_of_channels == 0)
{
number_of_channels = DEFAULT_NUMBER_OF_CHANNELS;
}
if((channel_logic != 0) && (channel_logic != 1))
{
channel_logic = DEFAULT_CHANNEL_LOGIC;
}
// we use "off" by default
// you can use EEPROM library to load/save default states
memset(pin_states, 0, number_of_channels);
// Dynamic config...
ZUNO_START_CONFIG();
for(i=0;i<number_of_channels;i++)
{
// add Z-Wave channel
ZUNO_ADD_CHANNEL(ZUNO_SWITCH_BINARY_CHANNEL_NUMBER, 0, 0)
// set pin to output
pinMode(pin_mapping[i], OUTPUT);
digitalWrite(pin_mapping[i],1); //channel_logic ? pin_states[i]: !(pin_states[i]));
}
ZUNO_COMMIT_CONFIG();
}
// the loop function runs over and over again forever
void loop() {
// We don't need loop here...
// All logic is located in zunoCallback
}
void zunoCallback(void)
{
// See callback_data variable
// We use zero based index of the channel instead of
// typical Getter/Setter index of Z-Uno.
// See enum ZUNO_CHANNEL*_GETTER/ZUNO_CHANNEL*_SETTER in ZUNO_Definitions.h
byte index = (callback_data.type & 0x03F);
index >>= 1;
// Configuration parameter was changed?
if(callback_data.type & CONFIG_DATA_FLAG)
{
if(callback_data.type & SETTER_BIT)
{
switch(index)
{
case 0:
number_of_channels = callback_data.param.bParam;
if(number_of_channels > sizeof(pin_mapping) || number_of_channels == 0)
number_of_channels = DEFAULT_NUMBER_OF_CHANNELS;
break;
case 1:
channel_logic = callback_data.param.bParam;
if((channel_logic != 0) && (channel_logic != 1))
channel_logic = DEFAULT_CHANNEL_LOGIC;
break;
default:
break;
}
zunoSaveCFGParam(64+index,&(callback_data.param.dwParam));
}
else
{
zunoLoadCFGParam(64+index,&(callback_data.param.dwParam));
}
return;
}
// It's a device channel event
if(callback_data.type & SETTER_BIT)
{
pin_states[index] = (callback_data.param.bParam != 0);
digitalWrite(pin_mapping[index], channel_logic ? pin_states[index]: !(pin_states[index]));
}
else
{
callback_data.param.bParam = pin_states[index];
}
}
Code: Select all
#include "Arduino.h"
void setup();
BYTE getSwitchMultilevelValue();
void setSwitchMultilevelValue(BYTE newValue);
void loop();
/*
Blink
Turns on an LED on for one second, then off for one second, repeatedly.
Z-Uno has an on-board LED you can control. It is attached to digital pin 13.
LED_BUILTIN is an internal Define which can be used to access this LED.
This example demonstrates the simple blink programm, where the blink interval can be changed from the Z-Wave controller.
More information on http:
*/
byte dimmerValue=100;
// ZUNO_SETUP_CHANNELS(ZUNO_SIREN(getSwitchMultilevelValue,setSwitchMultilevelValue));
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
dimmerValue = 100;
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(dimmerValue*10);
digitalWrite(LED_BUILTIN, LOW);
delay(dimmerValue*10);
}
void setSwitchMultilevelValue(byte newValue) {
dimmerValue = newValue;
}
byte getSwitchMultilevelValue(void) {
return dimmerValue;
}
// *********** uCxx section **********
// zunoCallback() was generated automatically by uCxx
void zunoCallback()
{
switch(callback_data->type)
{
case ZUNO_CHANNEL1_GETTER:
callback_data->param.bParam = getSwitchMultilevelValue();
break;
case ZUNO_CHANNEL1_SETTER:
setSwitchMultilevelValue(callback_data->param.bParam);
break;
default:
break;
}
}
// __zuno_autosetup() was generated automatically by uCxx
void __zuno_autosetup()
{
ZUNO_START_CONFIG();
ZUNO_ADD_CHANNEL(ZUNO_SIREN_CHANNEL_NUMBER, 0, 0);
ZUNO_COMMIT_CONFIG();
}
// *********************************
If we compare it with the code of n-channel switch some of things will become evident (you can take a look to core-files for more information about channel constants and etc). The main advantage of n-channel switch code listed bellow is size. It needs only 1,5k of code for 26-channel relay. It sounds good, doesn't it? You can use the same approach to reduce & simplify your code for projects when you need a number of the same channels. Another advantage of these code is setup of number of channels from Z-Wave controller without reflashing of the sketch.