Add IO to Vocore2 Ultimate

ArkEngr
 
Posts: 38
Joined: Tue Oct 20, 2015 1:58 pm

Add IO to Vocore2 Ultimate

Tue Oct 27, 2020 4:45 pm

I really like the nice little plastic box that the Vocore2 Ultimate comes in. But I needed some additional connections to it so I added a connector as shown in the attachment.
The pins connect to the Vocore2 at 4 pins next to each other of GND, 3.3V, GPIO37, GPIO38 which gives you 2 IO pins and power and ground. With this setup I first used the ground and GPIO37 to power an OPTO 22 Model 120D10 solid state relay for controlling AC lamps around my house. The addition of a web page shows status and allows editing of cron jobs for timed or manual control.
Then I got to looking at the SHT20 in Vonger's blog. I wrote the program below to bit bang the i2c interface. Works nice to show temperature and humidity.

#include "stdio.h"
#include "unistd.h"
#include "sys/ioctl.h"
#include "sys/mman.h"
#include "fcntl.h"
#include "time.h"

#define NULPTR ((unsigned long *)0)

#define I2C_DATA_LINE 37
#define I2C_CLOCK_LINE 38
#define I2C_DATA_IN 0
#define I2C_DATA_OUT 1


/* Set Bits 32 - 63 */
#define GPIO_DSET1 0x0634

/* Clear Bits 32 - 63 */
#define GPIO_DCLR1 0x0644

/* Value in/out Bits 32 - 63 */
#define GPIO_DATA1 0x0624

/* Direction Bits 32 - 63 */
#define GPIO_CTRL_1 0x0604

/* Data mask Bit 37 */
#define GPIO_DATA 0x00000020

/* CLK mask Bit 38 */
#define GPIO_CLK 0x00000040

#define MAX_BUF 64
#define PAGE_SIZE 4096
#define MEM_BASE 0x10000000
#define SYSFS_GPIO_DIR "/sys/class/gpio"

unsigned long *mem = NULPTR;

/* vocore */
/****************************************************************
* mmap_page returns pointer to memory
****************************************************************/
unsigned long *mmap_page(void)
{
signed long fd = -1;
unsigned long *fmem = NULPTR;

fd = open("/dev/mem", O_RDWR);

if(fd < 0)
{
return NULL;
}

fmem = (unsigned long *)mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, MEM_BASE);

close(fd);

return fmem;
}

/* vocore */
/****************************************************************
* gpio_set_dir
****************************************************************/
void gpio_set_dir(unsigned int gpio, unsigned int out_flag)
{
if(out_flag)
{
*((unsigned long *)(mem + (GPIO_CTRL_1 >> 2))) = GPIO_CLK | GPIO_DATA;
}
else
{
*((unsigned long *)(mem + (GPIO_CTRL_1 >> 2))) = GPIO_CLK;
}
}

/* vocore */
/****************************************************************
* gpio clear bits
****************************************************************/
void gpioclearbits(unsigned char data_pin)
{
if(data_pin == I2C_DATA_LINE)
{
*((unsigned long *)(mem + (GPIO_DCLR1 >> 2))) = GPIO_DATA;
}
else
{
*((unsigned long *)(mem + (GPIO_DCLR1 >> 2))) = GPIO_CLK;
}
}

/* vocore */
/****************************************************************
* gpio set bits
****************************************************************/
void gpiosetbits(unsigned char data_pin)
{
if(data_pin == I2C_DATA_LINE)
{
*((unsigned long *)(mem + (GPIO_DSET1 >> 2))) = GPIO_DATA;
}
else
{
*((unsigned long *)(mem + (GPIO_DSET1 >> 2))) = GPIO_CLK;
}
}

/* vocore */
/****************************************************************
* gpio get bit
****************************************************************/
int i2c_getbit(void)
{
if((*((unsigned long *)(mem + (GPIO_DATA1 >> 2))) & GPIO_DATA) == GPIO_DATA)
{
return(1);
}
return(0);
}

/* vocore reg */
/****************************************************************
* gpio set dir out
****************************************************************/
void i2c_clk_out(void)
{
gpio_set_dir(I2C_CLOCK_LINE, I2C_DATA_OUT);
}

/* vocore reg */
/****************************************************************
* gpio set dir out
****************************************************************/
void i2c_dir_out(void)
{
gpio_set_dir(I2C_DATA_LINE, I2C_DATA_OUT);
}

/* vocore reg */
/****************************************************************
* gpio set dir in
****************************************************************/
void i2c_dir_in(void)
{
gpio_set_dir(I2C_DATA_LINE, I2C_DATA_IN);
}

/* vocore reg */
/****************************************************************
* i2c data set state
****************************************************************/
void i2c_data(int state)
{
if(state == 1)
{
gpiosetbits(I2C_DATA_LINE);
}
else
{
gpioclearbits(I2C_DATA_LINE);
}
}

/* vocore reg */
/****************************************************************
* i2c clk set state
****************************************************************/
void i2c_clk(int state)
{
if(state == 1)
{
gpiosetbits(I2C_CLOCK_LINE);
}
else
{
gpioclearbits(I2C_CLOCK_LINE);
}
}

// Read a byte from I2C bus and send the ack sequence
// Put islast = 1 is this is the last byte to receive from the slave

unsigned char i2c_inbyte(int islast)
{
unsigned char value = 0;
int bitvalue;
int i;

i2c_dir_in();

for(i = 0; i < 8; i++)
{
usleep(100); // sleep for 0.2 milliseconds
bitvalue = i2c_getbit();
value |= bitvalue;

i2c_clk(1);

if(i < 7)
{
value <<= 1;
}

usleep(200); // sleep for 0.2 milliseconds
i2c_clk(0);
usleep(100); // sleep for 0.2 milliseconds
}

i2c_dir_out();

if(islast == 0)
{
// Send Ack if is not the last byte to read
i2c_data(0);

usleep(100); // sleep for 0.2 milliseconds
i2c_clk(1);
usleep(200); // sleep for 0.2 milliseconds
i2c_clk(0);
usleep(200); // sleep for 0.2 milliseconds
i2c_dir_in();
}
else
{
// Send Nack if is the last byte to read
i2c_data(1);

usleep(100); // sleep for 0.2 milliseconds
i2c_clk(1);
usleep(200); // sleep for 0.2 milliseconds
i2c_clk(0);
usleep(200); // sleep for 0.2 milliseconds
}

return value;
}


// Initializate the I2C bus

void i2c_init(void)
{
mem = mmap_page();

if(mem == NULL)
{
printf("can not map memory.\n");
return;
}

i2c_dir_out();
i2c_clk(1);
i2c_data(1);
}

// Send a start sequence to I2C bus
// Data goes low before Clock

void i2c_start(void)
{
i2c_data(0);
usleep(200); // sleep for 0.2 milliseconds
i2c_clk(0);
usleep(200); // sleep for 0.2 milliseconds
}

// Send a stop sequence to I2C bus
// Data goes high after Clock

void i2c_stop(void)
{
i2c_clk(1);
usleep(200); // sleep for 0.2 milliseconds
i2c_data(1);
usleep(200); // sleep for 0.2 milliseconds
}

// Send a byte to the I2C bus and return the ack sequence from slave
// rtc
// 0 = Nack, 1=Ack

int i2c_outbyte(unsigned char x)
{
int i;
int ack;

for(i = 0; i < 8; i++)
{

if(x & 0x80)
{
i2c_data(1);
}
else
{
i2c_data(0);
}

usleep(100); // sleep for 0.2 milliseconds
i2c_clk(1);
usleep(200); // sleep for 0.2 milliseconds
i2c_clk(0);
usleep(100); // sleep for 0.2 milliseconds

x <<= 1;
}

i2c_dir_in();
usleep(100); // sleep for 0.2 milliseconds
i2c_clk(1);
ack = i2c_getbit();
usleep(200); // sleep for 0.2 milliseconds
i2c_clk(0);

usleep(100); // sleep for 0.2 milliseconds
i2c_dir_out();
i2c_data(0);
usleep(100); // sleep for 0.2 milliseconds

if(ack == 0)
{
return 1;
}
else
{
return 0;
}
}

int main(void)
{
int loop_count;
int i2c_slave;
int RH, Temp;
unsigned char RH_hi, RH_lo, T_hi, T_lo, crc;
float RH_float, Temp_float;

printf("Temperature/Humidity ver 3.3\n");

i2c_init();

// SHT20
// | 1 | 0 | 0 | 0 || 0 | 0 | 0 | R/W |
i2c_slave = 0x80;

i2c_start();

if(i2c_outbyte(i2c_slave | 0) == 0)
{
printf("NACK received %d\n", __LINE__);
i2c_stop();
return -1;
}

if(i2c_outbyte(0xF5) == 0) /* Read Humidity */
{
printf("NACK received %d\n", __LINE__);
i2c_stop();
return -1;
}

usleep(5); // sleep for 5 useconds
i2c_stop();

loop_count = 0;

do /* Wait for Ack during measurement */
{
i2c_start();

if(i2c_outbyte(i2c_slave | 1) == 0)
{
i2c_stop();
usleep(5); // sleep for 5 useconds
printf("Meas NACK received %d\n", __LINE__);
}
else
{
break;
}

loop_count++;

} while(loop_count < 10000000);


RH_hi = i2c_inbyte(0);
RH_lo = i2c_inbyte(0);

crc = i2c_inbyte(1);

RH = (((unsigned int)(RH_hi)) << 8) + RH_lo;
RH = RH & 0xFFFC;
RH_float = RH;
RH_float = RH_float / 65536U;
RH_float = RH_float * 125.0f;
RH_float = RH_float - 6.0f;

i2c_stop();

// Show the humidity level
printf("Humidity = %6.2f %% (0x%02X 0x%02X)\n", RH_float, RH_hi, RH_lo);

i2c_start();

if(i2c_outbyte(i2c_slave | 0) == 0)
{
printf("NACK received %d\n", __LINE__);
i2c_stop();
return -1;
}

if(i2c_outbyte(0xF3) == 0) /* Read Temperature */
{
printf("NACK received %d\n", __LINE__);
i2c_stop();
return -1;
}

usleep(5); // sleep for 5 useconds
i2c_stop();

loop_count = 0;

do /* Wait for Ack during measurement */
{
i2c_start();

if(i2c_outbyte(i2c_slave | 1) == 0)
{
i2c_stop();
usleep(5); // sleep for 5 useconds
printf("Meas NACK received %d\n", __LINE__);
}
else
{
break;
}

loop_count++;

}while(loop_count < 10000000);


T_hi = i2c_inbyte(0);
T_lo = i2c_inbyte(0);

crc = i2c_inbyte(1);

Temp = (((unsigned int)(T_hi)) << 8) + T_lo;
Temp = Temp & 0xFFFC;
Temp_float = Temp;
Temp_float = Temp_float / 65536U;
Temp_float = Temp_float * 175.72f;
Temp_float = Temp_float - 46.85f;
Temp_float = (((Temp_float + 40.0f) * 9U) / 5U) - 40U;

i2c_stop();

// Show the humidity level
printf("Temperature = %6.2f deg. F (0x%02X 0x%02X)\n\n", Temp_float, T_hi, T_lo);

return 0;
}
Attachments
VocoreSmall.jpg
IO addition
VocoreSmall.jpg (155.72 KiB) Viewed 11627 times

ArkEngr
 
Posts: 38
Joined: Tue Oct 20, 2015 1:58 pm

Re: Add IO to Vocore2 Ultimate

Fri Nov 13, 2020 3:10 am

This is the web interface I made to run a light attached to the Vocore2 Ultimate via the SSR I mentioned.
Attachments
schededit.jpg
fancy way to edit the cron jobs on a web page
schededit.jpg (33.98 KiB) Viewed 11469 times
schedulecron.jpg
Displaying the schedule shows cron listing
schedulecron.jpg (28.73 KiB) Viewed 11469 times
mainscreen.jpg
Main web Screen for light control
mainscreen.jpg (25.87 KiB) Viewed 11469 times

ArkEngr
 
Posts: 38
Joined: Tue Oct 20, 2015 1:58 pm

Re: Add IO to Vocore2 Ultimate

Fri Nov 13, 2020 3:12 am

Hardware pictures
Attachments
powercontrolsmall.jpg
power box that controls light. SSR is in bottom of box and controls the top outlet
powercontrolsmall.jpg (138.8 KiB) Viewed 11469 times
temphumidsmall.jpg
Humidity sensor that works with code in post
temphumidsmall.jpg (225.33 KiB) Viewed 11469 times

Return to VoCore2/Lite/Ultimate

Who is online

Users browsing this forum: Google [Bot] and 59 guests