Why Arduino needs to be restarted after PS2 controller communication in Arduino? And how to to do this via coding? - interface

When I ran the code for a drivetrain and opened serial monitor it was working, but when I powered on Arduino via dc Jack and ran the code. It was not working, because code is needed to restart after connection. I want to know that how can I solve this problem of PS2 communication and run my drivetrain without restart or starting serial monitor.
Code that I uploaded was given in this instructable
http://www.instructables.com/id/Control-anything-with-ps2-controller-and-Arduino-/

I got my answer by experimenting a lot. First thing is that you have to either restart your arduino or configure your pin after connection of ps2 to arduino. This can be done by 2 ways :
1) Restart arduino after connection by code or
2) configure again after connection
1 option you know well, i am discussing 2nd i.e configure :
as you know that you have already configured pins by function ps2x.config_gamepad();
Now you have to reconfigure it after connection of ps2 to arduino, you can use a function called reconfig_gamepad(); after read_gamepad(); in void loop.
my code for holonomic drive train is below find out comments // there are total four commented lines in code. good luck. Hope this will solve your problem also.
#include <PS2X_lib.h> //for v1.6
int dir1=13;
int dir2=11;
int dir3=9;
int dir4=7;
int pwm1=12;
int pwm2=10;
int pwm3=8;
int pwm4=6;
int value_mapped;
/******************************************************************
* set pins connected to PS2 controller:
* - 1e column: original
* - 2e colmun: Stef?
* replace pin numbers by the ones you use
******************************************************************/
#define PS2_DAT 44 //14
#define PS2_CMD 46 //15
#define PS2_SEL 48 //16
#define PS2_CLK 50 //17
/******************************************************************
* select modes of PS2 controller:
* - pressures = analog reading of push-butttons
* - rumble = motor rumbling
* uncomment 1 of the lines for each mode selection
******************************************************************/
//#define pressures true
#define pressures false
//#define rumble true
#define rumble false
PS2X ps2x; // create PS2 Controller Class
//right now, the library does NOT support hot pluggable controllers, meaning
//you must always either restart your Arduino after you connect the controller,
//or call config_gamepad(pins) again after connecting the controller.
int error = 0;
byte type = 0;
byte vibrate = 0;
void setup(){
Serial.begin(57600);
pinMode(dir1,OUTPUT);
pinMode(dir2,OUTPUT);
pinMode(dir3,OUTPUT);
pinMode(dir4,OUTPUT);
pinMode(pwm1,OUTPUT);
pinMode(pwm2,OUTPUT);
pinMode(pwm3,OUTPUT);
pinMode(pwm4,OUTPUT);
delay(1000); //added delay to give wireless ps2 module some time to startup, before configuring it
//CHANGES for v1.6 HERE!!! **************PAY ATTENTION*************
if_error_is_found: // <!---- changed here --->
//setup pins and settings: GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error
error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble);
if(error == 0){
Serial.print("Found Controller, configured successful ");
Serial.print("pressures = ");
if (pressures)
Serial.println("true ");
else
Serial.println("false");
Serial.print("rumble = ");
if (rumble)
Serial.println("true)");
else
Serial.println("false");
Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;");
Serial.println("holding L1 or R1 will print out the analog stick values.");
Serial.println("Note: Go to www.billporter.info for updates and to report bugs.");
}
else if(error == 1)
{
Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips");
goto if_error_is_found; // <!---- changed here --->
}
else if(error == 2)
Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips");
else if(error == 3)
Serial.println("Controller refusing to enter Pressures mode, may not support it. ");
// Serial.print(ps2x.Analog(1), HEX);
type = ps2x.readType();
switch(type) {
case 0:
Serial.print("Unknown Controller type found ");
break;
case 1:
Serial.print("DualShock Controller found ");
break;
case 2:
Serial.print("GuitarHero Controller found ");
break;
case 3:
Serial.print("Wireless Sony DualShock Controller found ");
break;
}
}
void loop() {
/* You must Read Gamepad to get new values and set vibration values
ps2x.read_gamepad(small motor on/off, larger motor strenght from 0-255)
if you don't enable the rumble, use ps2x.read_gamepad(); with no values
You should call this at least once a second
*/
if(error == 1) //skip loop if no controller found
return;
if(type == 2){ //Guitar Hero Controller
ps2x.read_gamepad(); //read controller
if(ps2x.ButtonPressed(GREEN_FRET))
Serial.println("Green Fret Pressed");
if(ps2x.ButtonPressed(RED_FRET))
Serial.println("Red Fret Pressed");
if(ps2x.ButtonPressed(YELLOW_FRET))
Serial.println("Yellow Fret Pressed");
if(ps2x.ButtonPressed(BLUE_FRET))
Serial.println("Blue Fret Pressed");
if(ps2x.ButtonPressed(ORANGE_FRET))
Serial.println("Orange Fret Pressed");
if(ps2x.ButtonPressed(STAR_POWER))
Serial.println("Star Power Command");
if(ps2x.Button(UP_STRUM)) //will be TRUE as long as button is pressed
Serial.println("Up Strum");
if(ps2x.Button(DOWN_STRUM))
Serial.println("DOWN Strum");
if(ps2x.Button(PSB_START)) //will be TRUE as long as button is pressed
Serial.println("Start is being held");
if(ps2x.Button(PSB_SELECT))
Serial.println("Select is being held");
if(ps2x.Button(ORANGE_FRET)) { // print stick value IF TRUE
Serial.print("Wammy Bar Position:");
Serial.println(ps2x.Analog(WHAMMY_BAR), DEC);
}
}
else { //DualShock Controller
ps2x.read_gamepad(); //read controller and set large motor to spin at 'vibrate' speed
ps2x.reconfig_gamepad(); // <!---- changed here --->
if(ps2x.Button(PSB_START)) //will be TRUE as long as button is pressed
Serial.println("Start is being held");
if(ps2x.Button(PSB_SELECT))
Serial.println("Select is being held");
if(ps2x.Button(PSB_PAD_UP)) { //will be TRUE as long as button is pressed
Serial.print("Up held this hard: ");
Serial.println(ps2x.Analog(PSAB_PAD_UP), DEC);
}
if(ps2x.Button(PSB_PAD_RIGHT)){
Serial.print("Right held this hard: ");
Serial.println(ps2x.Analog(PSAB_PAD_RIGHT), DEC);
}
if(ps2x.Button(PSB_PAD_LEFT)){
Serial.print("LEFT held this hard: ");
Serial.println(ps2x.Analog(PSAB_PAD_LEFT), DEC);
}
if(ps2x.Button(PSB_PAD_DOWN)){
Serial.print("DOWN held this hard: ");
Serial.println(ps2x.Analog(PSAB_PAD_DOWN), DEC);
}
vibrate = ps2x.Analog(PSAB_CROSS); //this will set the large motor vibrate speed based on how hard you press the blue (X) button
if (ps2x.NewButtonState()) { //will be TRUE if any button changes state (on to off, or off to on)
if(ps2x.Button(PSB_L3))
Serial.println("L3 pressed");
if(ps2x.Button(PSB_R3))
Serial.println("R3 pressed");
if(ps2x.Button(PSB_L2))
Serial.println("L2 pressed");
if(ps2x.Button(PSB_R2))
Serial.println("R2 pressed");
if(ps2x.Button(PSB_TRIANGLE))
Serial.println("Triangle pressed");
}
if(ps2x.ButtonPressed(PSB_CIRCLE)) //will be TRUE if button was JUST pressed
Serial.println("Circle just pressed");
if(ps2x.NewButtonState(PSB_CROSS)) //will be TRUE if button was JUST pressed OR released
Serial.println("X just changed");
if(ps2x.ButtonReleased(PSB_SQUARE)) //will be TRUE if button was JUST released
Serial.println("Square just released");
// if(ps2x.Button(PSB_L1) || ps2x.Button(PSB_R1)) { //print stick values if either is TRUE
Serial.println("Stick Values:");
Serial.print(ps2x.Analog(PSS_LY), DEC); //Left stick, Y axis. Other options: LX, RY, RX
//Forward Direction And BAckward Diretion
if(ps2x.Button(PSB_R1)){
if(ps2x.Analog(PSS_RY)>=0)
{
//Forward Direction
if(ps2x.Analog(PSS_RY)<127)
{
Serial.println("All MOtor Running Forward");
digitalWrite(dir1,LOW);
digitalWrite(dir2,HIGH);
digitalWrite(dir3,HIGH);
digitalWrite(dir4,LOW);
value_mapped=map(ps2x.Analog(PSS_RY),127,0,0,80);
analogWrite(pwm1,value_mapped);
analogWrite(pwm2,value_mapped);
analogWrite(pwm3,value_mapped);
analogWrite(pwm4,value_mapped);
}
//BAckward Direction
if(ps2x.Analog(PSS_RY)>=127)
{
Serial.println("All MOtor Running Backward");
digitalWrite(dir1,HIGH);
digitalWrite(dir2,LOW);
digitalWrite(dir3,LOW);
digitalWrite(dir4,HIGH);
value_mapped=map(ps2x.Analog(PSS_RY),127,255,0,80);
analogWrite(pwm1,value_mapped);
analogWrite(pwm2,value_mapped);
analogWrite(pwm3,value_mapped);
analogWrite(pwm4,value_mapped);
}
}
// LEft OR Right Direction
if(ps2x.Analog(PSS_RX)>=0)
{
//Left diretion
if(ps2x.Analog(PSS_RX)<128)
{
Serial.println("All MOtor Running Left");
digitalWrite(dir1,HIGH);
digitalWrite(dir2,HIGH);
digitalWrite(dir3,LOW);
digitalWrite(dir4,LOW);
value_mapped=map(ps2x.Analog(PSS_RX),128,0,0,80);
analogWrite(pwm1,value_mapped);
analogWrite(pwm2,value_mapped);
analogWrite(pwm3,value_mapped);
analogWrite(pwm4,value_mapped);
}
//Right Direction
if(ps2x.Analog(PSS_RX)>128)
{
Serial.println("All MOtor Running Right");
digitalWrite(dir1,LOW);
digitalWrite(dir2,LOW);
digitalWrite(dir3,HIGH);
digitalWrite(dir4,HIGH);
value_mapped=map(ps2x.Analog(PSS_RX),128,255,0,80);
analogWrite(pwm1,value_mapped);
analogWrite(pwm2,value_mapped);
analogWrite(pwm3,value_mapped);
analogWrite(pwm4,value_mapped);
}
}
//All MOtors Clock
if( (ps2x.Analog(PSS_LX)<128) )
{
Serial.println("CLOCKWISE RUNNING ALL MOTORS");
digitalWrite(dir1,LOW);
digitalWrite(dir2,LOW);
digitalWrite(dir3,LOW);
digitalWrite(dir4,LOW);
value_mapped=map(ps2x.Analog(PSS_LX),128,0,0,80);
analogWrite(pwm1,value_mapped);
analogWrite(pwm2,value_mapped);
analogWrite(pwm3,value_mapped);
analogWrite(pwm4,value_mapped);
}
//All MOtors Anti-CLockwise
if(ps2x.Analog(PSS_LX)>128)
{
Serial.println("CLOCKWISE RUNNING ALL MOTORS");
digitalWrite(dir1,HIGH);
digitalWrite(dir2,HIGH);
digitalWrite(dir3,HIGH);
digitalWrite(dir4,HIGH);
value_mapped=map(ps2x.Analog(PSS_LX),128,255,0,80);
analogWrite(pwm1,value_mapped);
analogWrite(pwm2,value_mapped);
analogWrite(pwm3,value_mapped);
analogWrite(pwm4,value_mapped);
}
}
if(ps2x.Button(PSB_L1)){
if((ps2x.Analog(PSS_LX)>=120) && (ps2x.Analog(PSS_LX)<=128)){
analogWrite(pwm1,0);
analogWrite(pwm3,0);
}
//dIAGONAL L
if(ps2x.Analog(PSS_LX)<120)
{
Serial.println("CLOCKWISE RUNNING ALL MOTORS");
digitalWrite(dir1,LOW);
digitalWrite(dir3,HIGH);
value_mapped=map(ps2x.Analog(PSS_LX),128,0,0,80);
analogWrite(pwm1,value_mapped);
analogWrite(pwm3,value_mapped);
}
//dIAGONAL R
if(ps2x.Analog(PSS_LX)>=128)
{
Serial.println("CLOCKWISE RUNNING ALL MOTORS");
digitalWrite(dir2,HIGH);
digitalWrite(dir4,LOW);
value_mapped=map(ps2x.Analog(PSS_LX),128,255,0,80);
analogWrite(pwm2,value_mapped);
analogWrite(pwm4,value_mapped);
}
}
Serial.print(",");
Serial.print(ps2x.Analog(PSS_LX), DEC);
Serial.print(",");
Serial.print(ps2x.Analog(PSS_RY), DEC);
Serial.print(",");
Serial.println(ps2x.Analog(PSS_RX), DEC);
// }
}
delay(50);
}

Here's how I did it.....
void setup()
{
Serial.begin(9600);
// retry logic to avoid a reset after power up
do
{
delay(1000);
error = ps2x.config_gamepad(13, 11, 10, 12, true, true);
if (error == 1)
Serial.println("No controller found, retry in a sec");
} while (error == 1);
if (error == 0)
{
Serial.println("Found Controller, configured successful");
Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;");
Serial.println("holding L1 or R1 will print out the analog stick values.");
Serial.println("Go to www.billporter.info for updates and to report bugs.");
}
else if (error == 2)
Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips");
else if (error == 3)
Serial.println("Controller refusing to enter Pressures mode, may not support it. ");
type = ps2x.readType();
switch (type)
{
case 0:
Serial.println("Unknown Controller type");

Related

How can I change LED's brightness with PWM and USART in USART1_IRQHandler?

I am using STM32F4 discovery board and I am working on changing LED brightness and timer period using ADC and USART.
I use DMA to fetch ADC values, selected TIM4 for PWM and selected USART1 for USART. ADC, USART and PWM are working well so far, but USART1_IRQHandler() is not working as expected.
How can I adjust timer period and LED brightness with PWM and ADC in the following implementation of USART1_IRQHandler()?
void USART1_IRQHandler()
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) )
{
delay(168000);
i = USART_ReceiveData(USART1);
if(i == '1'){
TIMOC_InitStruct.TIM_Pulse=pwm_value;
TIM_OC1Init(TIM4,&TIMOC_InitStruct);
TIM_OC1PreloadConfig(TIM4,TIM_OCPreload_Enable);
UARTSend("3 led aktif\r\n",sizeof("LED 4 ON\r\n"));
}
else if(i == '2')
{
TIMOC_InitStruct.TIM_Pulse=pwm_value;
TIM_OC1Init(TIM4,&TIMOC_InitStruct);
TIM_OC1PreloadConfig(TIM4,TIM_OCPreload_Enable);
TIMOC_InitStruct.TIM_Pulse=pwm_value;
TIM_OC2Init(TIM4,&TIMOC_InitStruct);
TIM_OC2PreloadConfig(TIM4,TIM_OCPreload_Enable);
UARTSend("2 led aktif\r\n",sizeof("LED 4 ON\r\n"));
}
else if(i == '4')
{
TIMOC_InitStruct.TIM_Pulse=pwm_value;
TIM_OC1Init(TIM4,&TIMOC_InitStruct);
TIM_OC1PreloadConfig(TIM4,TIM_OCPreload_Enable);
TIMOC_InitStruct.TIM_Pulse=pwm_value;
TIM_OC2Init(TIM4,&TIMOC_InitStruct);
TIM_OC2PreloadConfig(TIM4,TIM_OCPreload_Enable);
TIMOC_InitStruct.TIM_Pulse=pwm_value;
TIM_OC3Init(TIM4,&TIMOC_InitStruct);
TIM_OC3PreloadConfig(TIM4,TIM_OCPreload_Enable);
UARTSend("4 led aktif\r\n",sizeof("LED 4 ON\r\n"));
}
else if(i == '4')
{
TIMOC_InitStruct.TIM_Pulse=pwm_value;
TIM_OC1Init(TIM4,&TIMOC_InitStruct);
TIM_OC1PreloadConfig(TIM4,TIM_OCPreload_Enable);
TIMOC_InitStruct.TIM_Pulse=pwm_value;
TIM_OC2Init(TIM4,&TIMOC_InitStruct);
TIM_OC2PreloadConfig(TIM4,TIM_OCPreload_Enable);
TIMOC_InitStruct.TIM_Pulse=pwm_value;
TIM_OC3Init(TIM4,&TIMOC_InitStruct);
TIM_OC3PreloadConfig(TIM4,TIM_OCPreload_Enable);
TIMOC_InitStruct.TIM_Pulse=pwm_value;
TIM_OC4Init(TIM4,&TIMOC_InitStruct);
TIM_OC4PreloadConfig(TIM4,TIM_OCPreload_Enable);
UARTSend("4 led aktif\r\n",sizeof("LED 4 ON\r\n"));
}
else
{
Hello();
UARTSend("Please enter another number:\n",sizeof("Please enter another number:\n"));
}
} USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
About your USART1_IRQHandler, have you check if the interrupt is active with
__HAL_RCC_UART4_CLK_ENABLE();
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
and if you enable it with this call
UART_Receive_IT( &huart1 );
I am using STM32Cube, repository V1.25.0.
Now, about your code inside the USART1_IRQHandler(), you could use shortcut to handle what you want to do. If I understand, you have 4 leds to control with the Timer4 and 4 channels.
The pulse is the Output Compare value (TIM4->CCR1 for channel 1). So, I would start the timer with a pulse equal to the Period (or zero. See note below).
From that point, if you want to change the brightness, you have just to change the pulse width with
__HAL_TIM_SET_COMPARE( htim4, TIM_CHANNEL_1, pwm_value);
or with
TIM4->CCR1 = pwm_value;
You could also disable any channel with
__HAL_TIM_DISABLE_IT( htim4, TIM_CHANNEL_1);
__HAL_TIM_ENABLE_IT( htim4, TIM_CHANNEL_1);
So, you get something like that
if(i == '1'){
TIM4->CCR1 = pwm_value;
} else if(i == '2') {
TIM4->CCR1 = pwm_value;
TIM4->CCR2 = pwm_value;
} ...
Note: I don't know how are connected your leds. If the led is connected to Vcc and the other end to the MPU pin, a LOW pulse will turn ON the led and HIGH pulse will turn it OFF.

I have two i2c devices. Both alone work well, but when I read from one, and then write to the other, the second one is not an ancknowledging

I have two devices MPU6050 and EEPROM 24C256. I can write and read from both alone. But when I try to read from MPU6050 and than write data to EEPROM in the same session, the EEPROM does not respond. I am using mbed OS libraries. And my question is.. Is it library, code or hardware problem?
MPU6050 read sequence:
enter image description here
EEPROM write page sequance:
enter image description here
//CODE
const char imuAddress = 0x68<<1;
const char imuDataAddress = 0x3B;
const char eepAddress = 0xA0;
const char data[3] = {1.1, 2.2, 3.3};
char acc[3];
//reading acceleration data from IMU
while(true){
i2c.start();
if(i2c.write(imuAddress) != 1){
i2c.stop();
continue;
}
if(i2c.write(imuDataAddress) != 1){
i2c.stop();
continue;
}
i2c.start();
if(i2c.write(imuAddress | 0x01) != 1){
i2c.stop();
continue;
}
for (int i = 0; i < 2; i++){
i2c.read(1); //read and respond ACK to continue
}
i2c.read(0); //read and respond NACK to stop reading
i2c.stop();
break;
}
//write data to EEPROM
while(true){
i2c.start();
if(i2c.write(eepAddress) != 1){ //here is the problem (EEPROM does not respond)
i2c.stop();
continue;
}
if(i2c.write(0x00) != 1){
i2c.stop();
continue;
}
if(i2c.write(0x00) != 1){
i2c.stop();
continue;
}
bool ack = true;
for(int i = 0; i < 3; i++){
if(i2c.write(data[i]) != 1){
i2c.stop();
ack = false;
break;
}
}
if (ack == true){
i2c.stop();
break;
}
}
I have a couple initial thoughts, but do you have access to an oscilloscope? It is odd that each one works individually. This makes me think that it may be an issue between the transition. (Possibly try a delay between each one? Also, possibly remove the stops in the initial read as they aren't necessary)
I think the best way to figure this out is to post a scope trace of the messaging for each one running individually and a trace of them running back to back.

Prevent error "funk" sound in event monitor OS X

I'm writing an app in swift that lives in the menu bar at the top of the screen. I need both a global and local event monitor to open the popover on a specific key press. There is no problem with the local event monitor, but when the user hits the key command (cmd+shift+8) from inside an app like Finder, the popover opens but the mac error "Funk" sound is played as well. Is there any way I can disable this? Perhaps some way for the app to eat the sound, or register it as a valid keyboard shortcut so the sound is never played?
Here is the code:
NSEvent.addGlobalMonitorForEvents(matching: NSEventMask.keyDown, handler: {(event: NSEvent!) -> Void in
if (event.keyCode == 28 && event.modifierFlags.contains(NSEventModifierFlags.command) && event.modifierFlags.contains(NSEventModifierFlags.shift)){
self.togglePopover(sender: self)
}
});
NSEvent.addLocalMonitorForEvents(matching: NSEventMask.keyDown, handler: {(event: NSEvent!) -> NSEvent? in
if (event.keyCode == 28 && event.modifierFlags.contains(NSEventModifierFlags.command) && event.modifierFlags.contains(NSEventModifierFlags.shift)){
self.togglePopover(sender: self)
}
return event
});
I ended up using MASShortcut as a workaround solution to this issue.
In your addGlobalMonitorForEventsMatchingMask handler, save the current volume level and turn the volume down on both channels. You can do you own event processing in the handler before or after turning down the volume.
Before returning from the handler, restore the original volume, but include a delay to give the OS time to process the event (it will send the "funk," but you won't hear it).
One side effect: if you're listening to something (e.g., music), that will be briefly silenced, too.
My event code:
[NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskKeyDown
handler:^(NSEvent *event) {
if ( event.type == NSEventTypeKeyDown ) {
if ( event.keyCode == 106 ) { // F16
// process the event here
[self adjustVolume:#(NO)];
[self performSelector:#selector(adjustVolume:) withObject:#(YES) afterDelay:0.3];
// 0.2 seconds was too soon
}
}
}];
My volume adjustment code:
- (void)adjustVolume:(NSNumber *)offOn
{
// get audio device...
AudioObjectPropertyAddress getDefaultOutputDevicePropertyAddress = {
kAudioHardwarePropertyDefaultOutputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
AudioDeviceID defaultOutputDeviceID;
UInt32 infoSize = sizeof(defaultOutputDeviceID);
AudioObjectGetPropertyData(kAudioObjectSystemObject,
&getDefaultOutputDevicePropertyAddress,
0, NULL,
&infoSize, &defaultOutputDeviceID);
// structurs to access the left/right volume setting
AudioObjectPropertyAddress volumePropertyAddress1 = {
kAudioDevicePropertyVolumeScalar,
kAudioDevicePropertyScopeOutput,
1 /* left */
};
AudioObjectPropertyAddress volumePropertyAddress2 = {
kAudioDevicePropertyVolumeScalar,
kAudioDevicePropertyScopeOutput,
2 /* right */
};
// save the original volume (assumes left/right are the same
static Float32 volumeOriginal; // could be an iVar
if ( offOn.boolValue == NO ) { // turn off
UInt32 volumedataSize = sizeof(volumeOriginal);
AudioObjectGetPropertyData(defaultOutputDeviceID,
&volumePropertyAddress1,
0, NULL,
&volumedataSize, &volumeOriginal);
//NSLog(#"volumeOriginal %f",volumeOriginal);
// turn off both channels
Float32 volume = 0.0;
AudioObjectSetPropertyData(defaultOutputDeviceID,
&volumePropertyAddress1,
0, NULL,
sizeof(volume), &volume);
AudioObjectSetPropertyData(defaultOutputDeviceID,
&volumePropertyAddress2,
0, NULL,
sizeof(volume), &volume);
} else { // restore
//NSLog(#"restoring volume");
AudioObjectSetPropertyData(defaultOutputDeviceID,
&volumePropertyAddress1,
0, NULL,
sizeof(volumeOriginal), &volumeOriginal);
AudioObjectSetPropertyData(defaultOutputDeviceID,
&volumePropertyAddress2,
0, NULL,
sizeof(volumeOriginal), &volumeOriginal);
}
}
With recognition to Thomas O'Dell for getting me started on this Change OS X system volume programmatically

Unity Touch phase returning incorrect results

In Unity, I am attempting to use Touch.
I am having non-stop issues with it and have decided to just try and get something simple working first.
Whenever i press the screen, i am expecting Touch.phase to return TouchPhase.Began every time. However, it will sometimes return TouchPhase.Stationary when touching the screen for the first time. I have also noticed that it will sometimes not call TouchPhase.Ended or TouchPhase.Canceled when the touch has left the screen. What am i doing wrong?
Here is my very simple code:
void FixedUpdate() {
if(Input.touchCount == 1) {
Touch touch = Input.GetTouch(0);
switch(touch.phase) {
case TouchPhase.Began:
Debug.Log("Began: " + touch.figerId);
break;
case TouchPhase.Stationary:
Debug.Log("Stationary");
break;
case TouchPhase.Moved:
Debug.Log("Moved");
break;
case TouchPhase.Canceled:
Debug.Log("Canceled");
break;
case TouchPhase.Ended:
Debug.Log("Ended");
break;
default:
Debug.Log("Default");
break;
}
}
}
Touch.phase is updated every frame, so you have to check it within the Update() method.
FixedUpdate() is only called every x frames (fixed framerate), that's the reason you are missing some of the touch phases.

Arduino sketch that reads serial characters as a command and does something

Currently I am trying to get a sketch working where the Arduino will read a series of characters as a command, and do something based on the series of characters sent from an iDevice. I am using an iPhone 3GS that is jailbroken to send characters to the Arduino. The method that sends the serial characters looks like the following,
- (IBAction)blinkFlow_A_LED:(id)sender {
// Method to blink the Flow_A LED on the kegboard-mini Arduino shield (<https://github.com/Kegbot/kegboard>).
NSLog(#"blink Flow_A btn pressed");
// Open serial port / interface
[serial open:B2400];
NSLog(#"%c", [serial isOpened]);
// Send serial data (TX)
char buffer [7];
buffer[0] = '{';
buffer[1] = 'b';
buffer[2] = 'l';
buffer[3] = 'i';
buffer[4] = 'n';
buffer[5] = 'k';
buffer[6] = '}';
[serial write:buffer length:7];
}
I have created a simple sketch that blinks the LED on the shield I am using, but I want the LED to blink conditionally when the button is clicked in the iOS app. The sketch that blinks the LED looks like the following,
/*
Blink
Turns on an LED on for one second, then off for one second, repeatedly.
This sketch is specific to making the kegboard-mini shield.
http://arduino.cc/forum/index.php?topic=157625.new;topicseen#new
This example code is in the public domain.
*/
// Pin D4 - should be connected to the flow_A LED
// Give it a name
int led = 4;
// The setup routine runs once when you press reset:
void setup() {
// Initialize the digital pin as an output.
pinMode(led, OUTPUT);
}
// The loop routine run over and over again forever:
void loop() {
digitalWrite(led, HIGH); // Turn the LED on (HIGH is the voltage level)
delay(1000); // Wait for one second
digitalWrite(led, LOW); // Turn the LED off by making the voltage LOW
delay(1000); // Wait for a second
}
That is a simple sketch!
You may want to begin with looking at the Arduino reference page: Serial
In setup(), you need at least Serial.begin(2400);.
Now, I'll suggest that reading and decoding the string "{blink}" seems like overkill. Let me suggest you send one character (for example 'b'), and detect one character, at least to start. Check out .available() and .read() on the Serial reference page. With these you can determine if a character has arrived at the Arduino and read in a single character.
You can then use these if you want to build a string of characters one at a time and compare it to String("{blink}"). This is a bit more complicated, especially if you take into account exceptions (like lost or damaged characters).
You can easily test your program using the Serial monitor tool -- just be advised that you have to hit "send" to make the characters go out.
I ended putting a simple sketch together like this which allows me to store an array of serial bytes into a String thanks to the SerialEvent example.
The sketch I am currently working with looks like the following,
/*
* kegboard-serial-simple-blink07
* This code is public domain
*
* This sketch sends a receives a multibyte String from the iPhone
* and performs functions on it.
*
* Examples:
* http://arduino.cc/en/Tutorial/SerialEvent
* http://arduino.cc/en/Serial/read
*/
// Global variables should be identified with "_"
// flow_A LED
int led = 4;
// relay_A
const int RELAY_A = A0;
// Variables from the sketch example
String inputString = ""; // A string to hold incoming data
boolean stringComplete = false; // Whether the string is complete
void setup() {
Serial.begin(2400); // Open a serial port. Sets data rate to 2400 bit/s
Serial.println("Power on test");
inputString.reserve(200);
pinMode(RELAY_A, OUTPUT);
}
void open_valve() {
digitalWrite(RELAY_A, HIGH); // Turn RELAY_A on
}
void close_valve() {
digitalWrite(RELAY_A, LOW); // Turn RELAY_A off
}
void flow_A_blink() {
digitalWrite(led, HIGH); // Turn the LED on (HIGH is the voltage level)
delay(1000); // Wait for one second
digitalWrite(led, LOW); // Turn the LED off by making the voltage LOW
delay(1000); // Wait for a second
}
void flow_A_blink_stop() {
digitalWrite(led, LOW);
}
void loop() {
// Print the string when newline arrives:
if (stringComplete) {
Serial.println(inputString);
// Clear the string:
inputString = "";
stringComplete = false;
}
if (inputString == "{blink_Flow_A}") {
flow_A_blink();
}
}
// SerialEvent occurs whenever a new data comes in the
// hardware serial RX. This routine is run between each
// time loop() runs, so using delay inside loop can delay
// response. Multiple bytes of data may be available.
void serialEvent() {
while(Serial.available()) {
// Get the new byte:
char inChar = (char)Serial.read();
// Add it to the inputString:
inputString += inChar;
// If the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}