Hackster is hosting Hackster Holidays, Ep. 4: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Wednesday!Stream Hackster Holidays, Ep. 4 on Wednesday!
Erik Brehl
Published

Balcony Wind Turbine

How can I generate electricity at home? Electrical current is not coming from the wall - it has to be generated somewhere.

IntermediateWork in progress1,126
Balcony Wind Turbine

Things used in this project

Hardware components

Cypress CY8CKIT-148 PSoC 4700S Inductive Sensing Evaluation Kit
Cypress CY8CKIT-148 PSoC 4700S Inductive Sensing Evaluation Kit
×1
E-Bike Motor 250W
×1
Bridge Rectifier 3 Phase
×1
Solar Charge Controller Victron Energy Blue Star 75/15
×1
Banner 12V Car Batterie 92Ah
×1
metal hardware for the turbines structure
×1
PVC Pipe 160mm
×1
STMicroelectronics STM32F407G-DISC1
×1
Windsensor WS2300-15
×1
PSoC 4 Prototyping Kit
Cypress PSoC 4 Prototyping Kit
×1

Software apps and online services

PSoC Creator
Cypress PSoC Creator
STMicroelectronics STM32CubeIDE

Hand tools and fabrication machines

Welding Machine GYSMI 160P
Weller Soldering Station

Story

Read more

Code

main_MagSense_Freq.c

C/C++
PSoC 4700S frequency calculation
/* ========================================
 *
 * Copyright YOUR COMPANY, THE YEAR
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF your company.
 *
 * ========================================
*/
#include "project.h"
#include "string.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/*****************************************************************************
* MACRO Definitions
*****************************************************************************/    
/* Boolean constants */
#define ON	    					(0u)
#define OFF 						(1u)
#define SET                         (1u)
#define CLEAR                       (0u)

/* Sets the levels for the proximity sensing */
#define LEVEL_1  					(100)
#define LEVEL_2						(1000)
#define LEVEL_3						(2000)
#define LEVEL_4						(3000)

/* Tuning related macros */

/* Percentage constants */
#define PERCENT_100                 (100)
#define PERCENT_70                  (70)

/* Raw count from CINTA integration */
#define CINTA_RESULT                (MagSense_RESULT_VAL1_REG & 0x0000ffff)

/* Raw count from CINTB integration */
#define CINTB_RESULT                (MagSense_RESULT_VAL2_REG & 0x0000ffff)

/* Pointer to scan parameters of the widget */
#define WD_STRUCT_PTR(w)            ((MagSense_RAM_WD_BASE_STRUCT *)(MagSense_dsFlash.wdgtArray[w].ptr2WdgtRam))

/* Half of scan period */
#define HALF_PERIOD_MAX(w)          (((((WD_STRUCT_PTR(w)->snsClk - MagSense_ISX_DEADBAND_CYCLES_NUMBER) * WD_STRUCT_PTR(w)->resolution)) + 1) >> 1)

/* Calculates x/y and rounds it up to next integer */
#define ROUND_DIVIDE(x, y)          (((x) + ((y) >> 1)) / (y))

/*****************************************************************************
* Variables
*****************************************************************************/ 

#define t_buf_max 6

char tx_buf[32];
char f_str[16];
char buf_full = '0';
char pulse_detected = '0';
int size_t_buf = t_buf_max;
int i_t_buf = 0;
uint_fast32_t t_buf[t_buf_max];
float curr_f = 0.0;        // aktuelle Drehfrequenz
float curr_rpm = 0.0;      // aktuelle Drehzahl

/*****************************************************************************
* Function Prototypes
*****************************************************************************/ 

void TuneMagSense(void);
void ConvFloat(float float_val, char *fstr);

/******************************************************************************
* Function Name: main
*******************************************************************************
*
* Summary: This is the main function. It configures the MagSense component and 
*          initiates scan of all the sensors. 
*
* Parameters:
*  None
*
* Return:
* int
*
******************************************************************************/

int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */

    /* Initialize MagSense Component */
    MagSense_Start();
    
    /* Tune the sensing parameters */
    TuneMagSense();
    
    /* Scan all the sensors */
    MagSense_ScanAllWidgets();
    
    UART_COM_Start();
    UART_COM_UartPutString("I am alive!\r\n");
    Pulse_out_Write(OFF);
                
    Timer_Pulse_Start();
    
    for(;;)
    {   
        /* Do this only when a scan is done */
        if(MagSense_NOT_BUSY == MagSense_IsBusy())
        {   
            /* Process all widgets */
            MagSense_ProcessAllWidgets(); 
            
            /* Run tuner */
            MagSense_RunTuner();   
            
            /* Check if proximity sensor is active */
            if(MagSense_IsProximitySensorActive(MagSense_PROXIMITY_EXT_WDGT_ID, MagSense_PROXIMITY_EXT_SNS0_ID))
            {
                if (pulse_detected == '0')
                {
                    t_buf[i_t_buf] = Timer_Pulse_ReadCounter();
                    
                    if(i_t_buf == (size_t_buf - 1))
                    {
                        buf_full = '1';
                        Timer_Pulse_Stop();
                    }
                    else
                    {
                        i_t_buf++;
                    }
                    
                    pulse_detected = '1';
                    Timer_Pulse_WriteCounter(0);
                    Timer_Pulse_Start();
                }
                
                /* Turn ON LED */
                LED_Level_1_Write(ON);
                LED_BTN1_Write(OFF);
                Pulse_out_Write(ON);
            }
            else                
            {
                pulse_detected = '0';
                /* Turn OFF LED */
                LED_Level_1_Write(OFF);
                Pulse_out_Write(OFF);                  
            }
            
            /* Start next scan */
            MagSense_ScanAllWidgets(); 
        }
        
        // frequency calculation
        if (buf_full == '1')
        {
            Timer_Pulse_Stop();
            MagSense_Stop();
            
            uint16 k = 0;              // counter meaning
            uint_fast32_t sum_T = 0;   // sum time differences 
            float delta_T = 0;         // mean value time differences
            
            for (int i = 1; i < size_t_buf; i++)
            {
                sum_T += t_buf[i];
                k++;
            }
                        
            delta_T = (float)sum_T / (float)k;
            curr_f = (float)14000 / delta_T / 2; // see timer clock
            curr_rpm = curr_f * 60; 

            buf_full = '0';
            pulse_detected = '0';
            i_t_buf = 0;
            
            for (int i=0; i < size_t_buf; i++) t_buf[i] = 0;
            for (uint i=0; i < sizeof(tx_buf); i++) tx_buf[i] = 0;
        
            ConvFloat(curr_f, f_str); 
            sprintf(tx_buf, "f=%s\r\n", f_str);
            UART_COM_UartPutString(tx_buf);
            CyDelay(100);
            
            MagSense_Start();
            Timer_Pulse_WriteCounter(0);
            Timer_Pulse_Start();
        }
        
        // no pulse for n seconds = timeout
        if(Timer_Pulse_ReadCounter() == Timer_Pulse_ReadPeriod())
        {
            curr_f = 0.0;
            curr_rpm = 0.0; 
            buf_full = '0';
            pulse_detected = '0';
            i_t_buf = 0;
            for (int i=0; i < size_t_buf; i++) t_buf[i] = 0;
            for (uint i=0; i < sizeof(tx_buf); i++) tx_buf[i] = 0;
                
            if (LED_BTN1_Read() == OFF)
            {
                LED_BTN1_Write(ON);
            }
            else
            {
                LED_BTN1_Write(OFF);
            }
            
            sprintf(tx_buf, "f=0.0\r\n");
            UART_COM_UartPutString(tx_buf);
            CyDelay(150);
            
            Timer_Pulse_WriteCounter(0);
            Timer_Pulse_Start();
        }
        
    }
}

/******************************************************************************
* Function Name: ConvFloat
******************************************************************************/

void ConvFloat(float float_val, char *fstr)
{
    char *tmpSign = (float_val < 0) ? "-" : "";
    float tmpVal = (float_val < 0) ? -float_val : float_val;

    int tmpInt1 = tmpVal;                  //get the integer
    float tmpFrac = tmpVal - tmpInt1;      //get fraction
    int tmpInt2 = trunc(tmpFrac * 10000);  //turn into integer

    //print as parts, note that you need 0-padding for fractional bit.

    sprintf (fstr, "%s%d.%02d", tmpSign, tmpInt1, tmpInt2);
}

/******************************************************************************
* Function Name: TuneMagSense
*******************************************************************************
*
* Summary: This function tunes the IDAC and the Lx clock frequency to accomodate 
*          the variations in coil parameters across the boards. Note that this 
*          function is a temporary bug fix and this fix will be incorporated in 
*          the next revision of the MagSense Component. 
*
* Parameters:
*  None
*
* Return:
*  None
*
******************************************************************************/
void TuneMagSense(void)
{
    uint8 widgetIter;
    uint16 biggerHalf;
    
    /* Tuning */
    for(widgetIter = 0; widgetIter < 3; widgetIter++)
    {
        /* Move buttons to more sensitive frequency. */
        WD_STRUCT_PTR(widgetIter)->snsClk += 3;
        
        /* Recalibrate Idacs for 70% sensitivity */
        MagSense_SetupWidget(widgetIter);
        
        /* Scan the sensor */
        MagSense_Scan();
        
        /* Wait till scan is complete */
        while(MagSense_IsBusy());
        
        /* Process the widget */
        MagSense_ProcessWidget(widgetIter);
        
        biggerHalf = CINTA_RESULT > CINTB_RESULT ? CINTA_RESULT : CINTB_RESULT;
        
        /* Update IDAC */
        WD_STRUCT_PTR(widgetIter)->idacMod[0] =
            ROUND_DIVIDE((WD_STRUCT_PTR(widgetIter)->idacMod[0] * biggerHalf * PERCENT_100),\
                (PERCENT_70 * HALF_PERIOD_MAX(widgetIter)));
    }    
}

/* [] END OF FILE */

main_ws2300-15.c

C/C++
Windsensor WS2300-15 decoding
/* ========================================
 *
 * Copyright YOUR COMPANY, THE YEAR
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF your company.
 *
 * ========================================
*/
#include "project.h"
#include "string.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

//=========================================
//variables
//=========================================

#define t_buf_max 5

uint8 mode = 1;
uint8 mes_len = 24;
uint8 pin_state = 1;
uint8 direction = 0;
uint16 wind = 0;
uint_fast16_t sleep_time = 1300; // 1300us = 1,3ms pro Bit
uint32 dataword = 0;
char tx_buf[32];

char f_str[16];
char buf_full = '0';
int size_t_buf = t_buf_max;
int i_t_buf = 0;
uint_fast32_t t_buf[t_buf_max];
uint8 Timeout_Counter = 0;
uint16 Counter_Period = 0;
float curr_f = 0.0;        //aktuelle Drehfrequenz
float curr_rpm = 0.0;      //aktuelle Drehzahl

CY_ISR(Timer_Pulse_Handler)
{
    t_buf[i_t_buf] = Timer_Pulse_ReadCapture();
    
    if(i_t_buf == (size_t_buf - 1))
    {
        buf_full = '1';
        Timer_Pulse_Stop();
        isr_Pulse_Stop();
        Timer_Pulse_ReadStatusRegister();
    }
    else
    {
        i_t_buf++;
    }
    
    Timeout_Counter = 0;
    Timer_Pulse_WriteCounter(Counter_Period);
    Timer_Pulse_ReadStatusRegister();
}

void ConvFloat(float float_val, char *fstr)
{
    char *tmpSign = (float_val < 0) ? "-" : "";
    float tmpVal = (float_val < 0) ? -float_val : float_val;

    int tmpInt1 = tmpVal;                  //get the integer
    float tmpFrac = tmpVal - tmpInt1;      //get fraction
    int tmpInt2 = trunc(tmpFrac * 10000);  //turn into integer

    //print as parts, note that you need 0-padding for fractional bit.

    sprintf (fstr, "%s%d.%02d", tmpSign, tmpInt1, tmpInt2);
}

//=========================================
//main program
//=========================================

int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */

    Pin_LED_Write(1);
    UART_Start();
    Timer_Pulse_Start();
    isr_Pulse_StartEx(Timer_Pulse_Handler);
    Counter_Period = Timer_Pulse_ReadPeriod();
    
    for(;;)
    {
        /* Place your application code here. */
        mode = Mode_Read();
        for (uint i=0; i < sizeof(tx_buf); i++) tx_buf[i] = 0;
        
        if (mode == 1)
        {
            dataword = 0;
            while(Data_In_Read() == 1)
            {
            }
           
            CyDelayUs(500); //sleep_time / 2); // Mitte des Bits
            
            for (uint8 i = 0; i < mes_len; i++)
            {
                pin_state = Data_In_Read(); 
                dataword += (pin_state << i);  
                CyDelayUs(sleep_time);
            }
            
            direction = (dataword >> 5) & 0x0f;
            wind = (dataword >> 9) & 0xff;
            
            //for (uint8 i=0; i < sizeof(tx_buf); i++) tx_buf[i] = 0;
            sprintf(tx_buf, "wind=%d\r\n", wind);
            UART_PutString(tx_buf);
            for (uint8 i=0; i < sizeof(tx_buf); i++) tx_buf[i] = 0;
            sprintf(tx_buf, "dir=%d\r\n", direction);
            UART_PutString(tx_buf);
        }
        else
        {
            if (buf_full == '1')
            {
                Timer_Pulse_Stop();
                isr_Pulse_Stop();
                
                uint16 k = 0;              //Anzahl Mittelungen
                uint_fast32_t sum_T = 0;   //Summe der Zeitdifferenzen
                float delta_T = 0;         //Mittelwert Zeitdifferenz
                
                for (int i = 1; i < size_t_buf; i++)
                {
                    sum_T += t_buf[i];
                    k++;
                }
                            
                delta_T = (float)Counter_Period - (float)sum_T / (float)k;
                curr_f = (float)15000 / delta_T;
                curr_rpm = curr_f * 60; 

                buf_full = '0';
                i_t_buf = 0;
                Timeout_Counter = 0;
                for (int i=0; i < size_t_buf; i++) t_buf[i] = 0;
                
                Timer_Pulse_WriteCounter(Counter_Period);
                Timer_Pulse_Start();
                isr_Pulse_StartEx(Timer_Pulse_Handler);
            }
            
            CyDelay(1000);
            Timeout_Counter++;
            
            if (Timeout_Counter >= 5)
            {
                curr_f = 0.0;
                curr_rpm = 0.0; 
                buf_full = '0';
                i_t_buf = 0;
                for (int i=0; i < size_t_buf; i++) t_buf[i] = 0;
            }
            
            ConvFloat(curr_f, f_str); 
            sprintf(tx_buf, "f=%s\r\n", f_str);
            UART_PutString(tx_buf);
            /*
            ConvFloat(curr_rpm, f_str); 
            sprintf(tx_buf, "rpm=%s\r\n", f_str);
            UART_PutString(tx_buf);
            */
        }
        
    }
}

/* [] END OF FILE */

Credits

Erik Brehl

Erik Brehl

1 project • 0 followers

Comments