I have 10 servo motor and I want to derive all of them.I used 2 timers interrupt with different timer frequency to generate different PWM frequency for each pin. the pins connected to servos, I derived one servo with each pin,
.the code is this:
Edited:
void TIM2_IRQHandler(void)
{
if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET )
{
TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);
GPIO_ResetBits(SERVO_PORT , FUEL_PIN);
GPIO_ResetBits(SERVO_PORT , SPEED_PIN);
GPIO_ResetBits(SERVO_PORT , RPM_PIN);
GPIO_ResetBits(SERVO_PORT , AIR_PRESURE_PIN);
GPIO_ResetBits(SERVO_PORT , OIL_ENGINE_PRESURE_PIN);
GPIO_ResetBits(SERVO_PORT , OIL_GEARBOX_PRESURE_PIN);
GPIO_ResetBits(SERVO_PORT , OIL_TEMPERATURE_PIN);
GPIO_ResetBits(SERVO_PORT , COOLER_WATER_TEMPERATURE_PIN);
//GPIO_ResetBits(GPIOD,GPIO_Pin_3);
CurrentDegree = 0;
}
}
void TIM4_IRQHandler(void)
{
if ( TIM_GetITStatus(TIM4 , TIM_IT_Update) != RESET )
{
TIM_ClearITPendingBit(TIM4 , TIM_FLAG_Update);
CurrentDegree++;
if(CurrentDegree < Desired)
{
GPIO_SetBits(GPIOD , GPIO_Pin_3);
}
else
{
GPIO_ResetBits(GPIOD,GPIO_Pin_3);
}
if(CurrentDegree < GetSpeed())
{
GPIO_SetBits(SERVO_PORT , SPEED_PIN);
}
else
{
GPIO_ResetBits(SERVO_PORT , SPEED_PIN);
}
if(CurrentDegree < GetRpm())
{
GPIO_SetBits(SERVO_PORT , RPM_PIN);
}
else
{
GPIO_ResetBits(SERVO_PORT , RPM_PIN);
}
if(CurrentDegree < GetFuel())
{
GPIO_SetBits(SERVO_PORT , FUEL_PIN);
}
else
{
GPIO_ResetBits(SERVO_PORT , FUEL_PIN);
}
if(CurrentDegree < GetAirPresure())
{
GPIO_SetBits(SERVO_PORT , AIR_PRESURE_PIN);
}
else
{
GPIO_ResetBits(SERVO_PORT , AIR_PRESURE_PIN);
}
if(CurrentDegree < GetOilEnginePresure())
{
GPIO_SetBits(SERVO_PORT , OIL_ENGINE_PRESURE_PIN);
}
else
{
GPIO_ResetBits(SERVO_PORT , OIL_ENGINE_PRESURE_PIN);
}
if(CurrentDegree < GetOilGearboxPresure())
{
GPIO_SetBits(SERVO_PORT , OIL_GEARBOX_PRESURE_PIN);
}
else
{
GPIO_ResetBits(SERVO_PORT , OIL_GEARBOX_PRESURE_PIN);
}
if(CurrentDegree < GetOilTemperature())
{
GPIO_SetBits(SERVO_PORT , OIL_TEMPERATURE_PIN);
}
else
{
GPIO_ResetBits(SERVO_PORT , OIL_TEMPERATURE_PIN);
}
if(CurrentDegree < GetCoolerWaterTemperature())
{
GPIO_SetBits(SERVO_PORT , COOLER_WATER_TEMPERATURE_PIN);
}
else
{
GPIO_ResetBits(SERVO_PORT , COOLER_WATER_TEMPERATURE_PIN);
}
}
}
the generated pwm works fine for 5 pins in port A. but when I increase the number of ports, the stm32 hangs.
how I can to increase pins?
if you have multi servo motors more than PWM Channels, so you can use PWM Genrator IC like TL594, find it in the web!
Since you omitted a few important details like the part number of your MCU, or the so-called MCVE, I can only guess here.
As you are adding more instructions to it, your timer interrupt may not finish before the next one comes. You can decrease the interrupt frequency, but it would make more sense to abandon software interrupts and use the hardware PWM generators.
STM32 general-purpose timers have up to 4 PWM outputs.
Edit: in an earlier port you've mentioned that you are using STM32F103RET. That MCU actually has 24 hardware PWM outputs.
See the chapter on general purpose timers in your reference manual, or section 2.5 in ST Application note AN2403 STM32 cross-series timer overview on how to use them.
You have 3 choice! 1)use encoders ic or2) pwm generator ic or3)just use multi arm cortex!
Related
To turn on the led the switch is to be pressed for 2 times,turn off the led the switch is to be pressed 3 times within 10 second?can any one explain the logic how to implement it?
I checked the status of a switch in delay function, but it's not working
#include<reg51.h>
void delay_ms(unsigned int );
int count=0;
sbit sw=P2^0;
sbit led=P1^0;
main()
{
while(1)
{
if(sw==0)
{
delay_ms(10000);
}
}
}
void delay_ms(unsigned int i)
{
int j;
for(i;i>0;i--)
for(j=122;j>0;j--)
{
if(sw==0)
{
while(sw==0);
count++;
if(count==2)
led=1;
if(count==3)
led=0;
}
}
}
expected result- switch pressed 2 times should turn on led and
switch pressed 3 times should turn off led (within 10 sec)
actual result- switch pressed 2 times should turn on led and
switch pressed 3 times should turn off led (but works without any time limit)
An alternative and more flexible solution (in an application where you might need to do other work concurrently), is to timestamp the switch events and compare the current event time with the previous timestamps.
Given a regular time source (assuming the standard clock() here but the logic is valid regardless) :
#include <time.h>
#include <string.h> // for memset()
#include <stdbool.h>
bool isSwitchEvent()
{
sbit sw = P2^0 ;
bit current_sw = sw ;
static bit previous_sw = sw ;
// NOTE: Ignoring switch bounce issues - different question
// Switch event when state *changed* to 1->0...
bool switch_event = (current_sw == 0 && previous_sw == 1) ;
previous_sw = current_sw ;
return switch_event ;
}
#define SWITCH_PERIOD CLOCKS_PER_SEC * 10
int main()
{
sbit led = P1^0;
// Initialise so that first switch event is guaranteed to be at
// least then 10 seconds later than the initial timestamps.
clock_t switch_timestamp[3] = {-SWITCH_PERIOD,
-SWITCH_PERIOD,
-SWITCH_PERIOD } ;
unsigned i = 0 ;
bit led_state = 0 ;
bool change = false ;
for(;;)
{
// On switch event...
if( isSwitchEvent() )
{
// Timestamp event
switch_timestamp[i] = clock() ;
// If LED off, and previous event was less
// than 10 seconds ago...
if( led_state = 0 &&
switch_timestamp[i] - switch_timestamp[(i+2)%3] < SWITCH_PERIOD )
{
// LED on
led_state = 1 ;
change = true ;
}
// else if LED on, and previous two events were less
// than 10 seconds ago...
else if( led_state = 1 &&
switch_timestamp[i] - switch_timestamp[(i+1)%3] < SWITCH_PERIOD )
{
// LED off
led_state = 0 ;
change = true ;
}
// If LED state change...
if( change )
{
// Set output to the prevailing LED state
led = led_state ;
// Make timestamps older that SWITCH_PERIOD so
// previous events are not to be counted
// for next LED state change.
switch_timestamp[0] = clock() - SWITCH_PERIOD ;
switch_timestamp[1] = switch_timestamp[0] ;
switch_timestamp[2] = switch_timestamp[0] ;
// Next timestamp
i++ ;
i %= 3 ;
}
}
// You can do other work here (so long as
// it does not take so long as to miss a
// switch event).
}
return 0 ;
}
The issue is that you are not providing any debounce for your switch. Also where is count being initialized? I don't see it.
You need to have a delay when you detect the switch closed because it will "bounce" open and closed many times in the first few milliseconds. I would delay for at least 10mS before checking to see if the switch has been opened and then you can change your count.
UPDATE BASED ON OP COMMENTS:
Well again, this would only work in simulation. Switches are not that good. But I do see your issue: You don't reset count in your main(). Try:
main()
{
while(1)
{
count = 0;
if(sw==0)
{
delay_ms(10000);
}
}
}
I have some time controlled segments inside my main loop that turning LEDs on/off and are storing values from a sensor into a linked list (Using this linked list library: https://github.com/ivanseidel/LinkedList). I have my baud rate set at 34800 because I want data to be transferred at a faster rate, and I have a a function that for loops the sensor data captured within the the timed loops and prints them.
The weird problem I'm facing is when I Serial.print() the data, it only works when I have a Serial.println()(just Serial.print() does not work) inside each of the if blocks. If I remove this Serial.println() the code does not work, and just gives out garbage in the Serial monitor.
What is causing this issue? How do I resolve it? Here is the code:
void setup( void )
{
Serial.begin( 38400 );
while(!Serial){
}
pinMode (ledPin670, OUTPUT);
pinMode (ledPin850, OUTPUT);
digitalWrite(ledPin670,HIGH);
digitalWrite(ledPin850,HIGH);
Start = millis();
timer = micros();
}
void loop( void )
{
if ( millis() - Start < 100 )
{
//Serial.read();
Serial.println(" ");
digitalWrite(ledPin670,LOW);
analogRead( A0 );
valList670.add(analogRead( A0 ));
time670.add(micros() - timer);
++Count;
}
else if ((millis() - Start >= 100) && (millis() - Start < 110)){
digitalWrite(ledPin670,HIGH);
}
else if ((millis() - Start >= 110) && (millis() - Start < 220))
{
// Serial.read();
Serial.println(" ");
digitalWrite(ledPin670,HIGH);
digitalWrite(ledPin850,LOW);
analogRead( A0 );
valList950.add(analogRead( A0 ));
time850.add(micros() - timer);
++Count2;
}
else if ((millis() - Start >= 220) && (millis() - Start < 230)){
digitalWrite(ledPin850,HIGH);
else
{
//Serial.println(millis() - Start);
Serial.println("count:");
Serial.println( Count );
Serial.println( Count2 );
Serial.println( Count3 );
arrayLoop(valList670, time670,10);
arrayLoop(valList850, time850,10);
valList670.clear();
valList850.clear();
time850.clear();
time670.clear();
timer = micros();
Count = 0;
Count2 = 0;
Start = millis();
}
void arrayLoop(LinkedList<int> &pinNum,LinkedList<unsigned long> &timer, int valDiff){
// Serial.println(pinNum);
int listSize = pinNum.size();
for (int h = 0; h < listSize; h+=valDiff) {
//Get value from list
if (h <= listSize){
int val = pinNum.get(h);
unsigned long tim = timer.get(h);
Serial.print(tim);
Serial.print("\t");
Serial.println(val);
}
}
}
Only call Serial.print() once.
If you define the circumstances under which you do, and do not, want to call Serial.print(), we can help you see that it happens that way.
Basically, though, you need to count how many times you have already printed. Only actually call print if the count is 0.
I am having a problem that I asked here but as the problem has changed somewhat, as has the code, I am starting a new question
I am trying to read and write values from an array of struct via the function
void BreezeMapPixels(struct_displayType& mDisplayUnit, int breezeStrength)
The values I am getting from the Serial.print are not those stored in the array. Specifically the one for endLed, which should never be 0
Output from Serial
Breeze Module
Start 8 End 0
Breeze Module
Start 1 End 0
Breeze Module
Start 1 End 0
Breeze Module
Start 4 End 7
These are defined as
// Define each display's LED range
{
displayUnit[0].startLed=0;
displayUnit[0].endLed=3;
displayUnit[1].startLed=4;
displayUnit[1].endLed=7;
displayUnit[2].startLed=8;
displayUnit[2].endLed=11;
displayUnit[3].startLed=12;
displayUnit[3].endLed=15;
}
Also the program seems to freze after a while.
Any help as to why I am reading the wrong values would be appreciated.
Full Code
/* **********************************
Breeze
* *********************************/
// Designed to illuminate a 'map' of pixels, each of which randomly
// sometimes twinkles brighter and then back down to it's base color again.
//
/* **********************************
Start of Code
* *********************************/
enum { SteadyDim, GettingBrighter, GettingDimmerAgain };
void InitPixelStates(struct_displayType& mDisplayUnit)
{
for ( uint16_t i = mDisplayUnit.startLed; i <= mDisplayUnit.endLed; i++) {
leds[i]=BASE_COLOR;
}
}
void BreezeMapPixels(struct_displayType& mDisplayUnit, int breezeStrength)
{
Serial.println("Breeze Module");
Serial.print("Start ");
Serial.print(mDisplayUnit.startLed);
Serial.print(" End " );
Serial.println(mDisplayUnit.endLed);
for ( uint16_t i = mDisplayUnit.startLed; i <= mDisplayUnit.endLed; i++) {
Serial.print(" pixel state " );
Serial.println(mDisplayUnit.pixelState[i] );
Serial.println(GettingBrighter);
Serial.println(GettingDimmerAgain);
Serial.println(SteadyDim);
if ( mDisplayUnit.pixelState[i] == SteadyDim) {
// this pixels is currently: SteadyDim
// so we randomly consider making it start getting brighter
leds[i]=BASE_COLOR;
if ( random8() < breezeStrength) {
mDisplayUnit.pixelState[i] = GettingBrighter;
}
} else if ( mDisplayUnit.pixelState[i] == GettingBrighter ) {
Serial.println("Brighter " + i);
// this pixels is currently: GettingBrighter
// so if it's at peak color, switch it to getting dimmer again
if ( leds[i] >= PEAK_COLOR ) {
mDisplayUnit.pixelState[i] = GettingDimmerAgain;
} else {
// otherwise, just keep brightening it:
leds[i] += DELTA_COLOR_UP;
}
} else { // getting dimmer again
Serial.println("Dimmer " + i);
// this pixels is currently: GettingDimmerAgain
// so if it's back to base color, switch it to steady dim
if ( leds[i] <= BASE_COLOR ) {
leds[i] = BASE_COLOR; // reset to exact base color, in case we overshot
mDisplayUnit.pixelState[i] = SteadyDim;
} else {
// otherwise, just keep dimming it down:
leds[i] -= DELTA_COLOR_DOWN;
}
}
}
}
void loop() {
photoCell = analogRead(pin);
time = millis();
if (photoCell >= 400){
timeon = millis();
led = 1;
while (analogRead(pin) >= 400) {
timer = millis() - timeon;
//Serial.print("On");
//Serial.println(timer);
}
}
if (photoCell <= 400) {
timeoff = millis();
led = 0;
while (analogRead(pin) <= 400) {
timer2 = millis() - timeoff;
//Serial.print("Off");
//Serial.println(timer2);
}
}
if (timer >= 175 && timer <= 200 && led == 1) {
Serial.print("Char = ");
Serial.println(".");
codearray[i] = 8;
i++;
}
if (timer >= 580 && timer <= 600 && led == 1) {
Serial.print("Char = ");
Serial.println("-");
codearray[i] = 9;
i++;
}
This is my current code which works fine using a photocell plugged into A0 and an led wired into pin 9. The serial monitor displays whether or not I am flashing a dot or dash, morse corde, based on the timing.
However.. When I add this bit of code
if (codearray[0] == 8 && codearray[1] == 8 &&
codearray[2] == 8 && codearray[3] == 0) {
Serial.print("s");
}
The monitor prints nothing. This bit of code fills out an array I set up so I can print back into alphabetical the morse code that was deciphered. I'm pretty sure my logic is correct.
Looking to see if anyone understands why the 2nd bit of code would conflict with the first or what can be wrong with the analog input or serial monitor.
Your question is off topic here; probably belongs on stack overflow.
But it is obvious that you forgot to call Serial.Begin(9600); in setup(); n.b. 9600 is the arduino default baud rate.
I am using a LDR to tell me whether there is light or not with an Arduino. My code is pretty simple, but instead of spamming "light light light light" I would like it to say "light" once, and then if the light goes off, for it to say "No light" once.
code edited from "readanalogvoltage":
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (5.0 / 1023.0);
// print out the value you read:
if (voltage > 1.5)
{
Serial.print("Light");
Serial.println();
delay(5000);
}
if (voltage < 1.5)
{
Serial.print("No Light");
Serial.println();
delay(50);
}
}
Keep a variable that holds the last state:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
int wasLit = 0;
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (5.0 / 1023.0);
// print out the value you read:
if (!wasLit && voltage > 1.5) {
wasLit = 1;
Serial.print("Light");
Serial.println();
delay(5000);
} else if(wasLit && voltage <= 1.5) {
wasLit = 0;
Serial.print("No Light");
Serial.println();
delay(50);
}
}
This sort of test will benefit from use of hysterisis. Especially if you have flourescent light, there will be some flicker. That will cause the sensor reading to vary such that it may not change from <1.5 to >=1.5 in a clean manner.
boolean bLast = false;
const float vTrip = 1.5;
// you find a good value for this by looking at the noise in readings
// use a scratch program to just read in a loop
// set this value to something much larger than any variation
const float vHyst = 0.1;
float getLight() {
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (5.0 / 1023.0);
return voltage;
}
void setup() {
// establish the initial state of the light
float v = getLight();
bLast = ( v < (vTrip-vHyst) );
}
void loop() {
float v = getLight();
if( bLast ) {
// light was on
// when looking for decreasing light, test the low limit
if( v < (vTrip-vHyst) ) {
bLast = false;
Serial.print("Dark");
}
}
else {
// light was off
// when looking for increasing light, test the high limit
if( v > (vTrip+vHyst) ) {
bLast = true;
Serial.print("Light");
}
}
}